<template>
<view class="live-camera" :style="{ width: windowWidth, height: windowHeight }">
<view class="preview" :style="{ width: windowWidth, height: windowHeight}">
<live-pusher
id="livePusher"
ref="livePusher"
class="livePusher"
mode="FHD"
beauty="0"
whiteness="0"
:aspect="aspect"
min-bitrate="1000"
audio-quality="16KHz"
:device-position="devicePosition"
remote-mirror="false"
:auto-focus="true"
:muted="true"
:enable-camera="true"
:enable-mic="false"
:zoom="false"
:style="{ width: windowWidth, height: windowHeight }"
></live-pusher>
<!--提示语-->
<cover-view class="add-remind">
<text class="remind-text" @click="showIcon=true">添加水印</text>
</cover-view>
<!-- 可添加水印列表 -->
<cover-view class="icon-list" v-if="showIcon">
<image v-for="(item,index) in iconList" class="icon-img" :src="item.img" :key="index" @click="addWatermark(item, index)"></image>
</cover-view>
<!-- 已添加水印列表 -->
<template v-for="(item,index) in activeIcon" >
<view class="active-icon-img-wrap" :key="index" :style="{ top: item.moveY+'px', left: item.moveX+'px' }" @touchstart="dragStart(index,$event)" @touchmove.stop="dragMove(index,$event)">
<image class="active-icon-img" :src="item.img" ></image>
</view>
</template>
</view>
<!--底部菜单区域背景-->
<view class="menu">
<cover-image class="menu-mask" src="../../static/image/watermark/bar.png"></cover-image>
<!--返回键-->
<cover-image class="menu-back" @tap="back" src="../../static/image/watermark/back.png"></cover-image>
<!--快门键-->
<cover-image class="menu-snapshot" @tap="snapshot" src="../../static/image/watermark/shutter.png"></cover-image>
<!--反转键-->
<cover-image class="menu-flip" @tap="flip" src="../../static/image/watermark/flip.png"></cover-image>
</view>
</view>
</template>
<script>
let _this = null;
export default {
data() {
return {
dotype:'watermark',
devicePosition: 'back', // 前后摄像头
message:'live-camer',//水印内容
aspect: '2:3', //比例
windowWidth: '', //屏幕可用宽度
windowHeight: '', //屏幕可用高度
camerastate: false, //相机准备好了
livePusher: null, //流视频对象
snapshotsrc: null, //快照
iconList:[
{ img: '/static/image/flower.png', moveX: 20, moveY: 80, delShow: false },
{ img: '/static/image/flowerS.png', moveX: 20, moveY: 120, delShow: false },
{ img: '/static/image/home.png', moveX: 20, moveY: 160, delShow: false },
{ img: '/static/image/homeS.png', moveX: 20, moveY: 200, delShow: false },
],
activeIcon: [],
moveStart: [0,0], // 水印被拖动时的初始位置
showIcon: false, // 是否显示可添加水印列表
systemInfo: {},
moveOver: false
};
},
onShow(e) {
if(this.livePusher) {
this.initData()
this.startPreview()
}
},
onReady() {
console.log('ready')
_this = this;
this.livePusher = uni.createLivePusherContext('livePusher', this);
uni.getSystemInfo({
success: function(res) {
_this.systemInfo = res
_this.devicePosition = _this.systemInfo.platform == 'ios' ? 'front' : 'back'
}
});
this.initCamera();
setTimeout(()=> {
this.startPreview(); //开启预览并设置摄像头
},50)
},
methods: {
//初始化相机
initCamera() {
this.windowWidth = this.systemInfo.windowWidth;
this.windowHeight = this.systemInfo.windowHeight;
let zcs = this.aliquot(this.windowWidth, this.windowHeight);
this.aspect = this.windowWidth / zcs + ':' + this.windowHeight / zcs;
},
// 图片页面返回初始化数据
initData() {
this.activeIcon = []
this.showIcon = false
},
//整除数计算
aliquot(x, y) {
if (x % y == 0) return y;
return this.aliquot(y, x % y);
},
//开始预览
startPreview() {
this.livePusher.startPreview({
success: a => {
// ios默认前置摄像头,反转它
console.log(this.devicePosition == 'front')
if(this.systemInfo.platform == 'ios' && this.devicePosition == 'front') this.flip()
},
fail: err => {
console.log(err);
},
complete(data) {
console.log(data)
}
});
},
//停止预览
stopPreview() {
this.livePusher.stopPreview({
success: a => {
_this.camerastate = false; //标记相机未启动
}
});
},
//返回
back() {
uni.navigateBack();
},
//抓拍
snapshot() {
this.livePusher.snapshot({
success: e => {
_this.snapshotsrc = e.message.tempImagePath;
_this.stopPreview();
// 先将临时文件保存到本地 否则canvas画完输出ios有安全问题
uni.saveFile({
tempFilePath: e.message.tempImagePath,
success: (res) => {
uni.setStorageSync('canvasPreview', { path: res.savedFilePath, iconInfo: _this.activeIcon, devicePosition: this.devicePosition })
}
});
uni.navigateTo({
url: '/pages/test/waterPreview'
})
}
});
},
//反转
flip() {
this.livePusher.switchCamera();
this.devicePosition = this.devicePosition == 'front' ? 'back' : 'front'
console.log(this.devicePosition)
},
// 添加水印
addWatermark(item) {
let data = JSON.parse(JSON.stringify(item))
this.activeIcon = this.activeIcon.concat(data)
},
// 开始拖动
dragStart(index,event) {
// console.log(this.activeIcon[index].moveX,event.touches[0])
// this.activeIcon[index].moveX = event.touches[0].pageX
// this.activeIcon[index].moveY = event.touches[0].pageY
// console.log(this.activeIcon[index].moveX)
},
// 托动
dragMove(index,event){
let tag = event.touches;
if(tag[0].pageX < 0 ){
tag[0].pageX = 0
}
if(tag[0].pageY < 0 ){
tag[0].pageY = 0
}
if(tag[0].pageX > this.windowWidth ){
tag[0].pageX = this.windowWidth
}
if(tag[0].pageY > this.windowHeight ){
tag[0].pageY = this.windowHeight
}
this.activeIcon[index].moveX = tag[0].pageX;
this.activeIcon[index].moveY = tag[0].pageY;
},
}
};
</script>
<style lang="scss">
.live-camera {
justify-content: center;
align-items: center;
position: relative;
height: 100vh;
}
.menu {
position: absolute;
left: 0;
bottom: 0;
width: 750rpx;
height: 180rpx;
z-index: 98;
align-items: center;
justify-content: center;
}
.menu-snapshot {
width: 130rpx;
height: 130rpx;
z-index: 99;
}
.menu-mask {
position: absolute;
left: 0;
bottom: 0;
width: 750rpx;
height: 180rpx;
z-index: 98;
}
.menu-back {
position: absolute;
left: 30rpx;
bottom: 50rpx;
width: 80rpx;
height: 80rpx;
z-index: 99;
align-items: center;
justify-content: center;
}
.menu-flip {
position: absolute;
right: 30rpx;
bottom: 50rpx;
width: 80rpx;
height: 80rpx;
z-index: 99;
align-items: center;
justify-content: center;
}
.preview {
justify-content: center;
align-items: center;
}
.add-remind {
position: absolute;
top: 20rpx;
right: 20rpx;
z-index: 100;
}
.remind-text {
color: #dddddd;
font-size: 28rpx;
// text-shadow: #fff 1px 0 0, #fff 0 1px 0, #fff -1px 0 0, #fff 0 -1px 0;
}
.icon-list {
height: 100rpx;
display: flex;
// background-color: rgba($color: #000000, $alpha: 0.1);
flex-direction: row;
align-items: center;
position: absolute;
bottom: 180rpx;
left: 0;
right: 0;
}
.icon-img {
height: 80rpx;
width: 80rpx;
margin-right: 20rpx;
}
.active-icon-img-wrap {
height: 80rpx;
width: 80rpx;;
position: absolute;
z-index: 100;
}
.active-icon-img {
height: 80rpx;
width: 80rpx;
}
.iconfont {
width: 30rpx;
height: 30rpx;
border-radius: 15rpx;
position: absolute;
background-color: #ccc;
top: 0;
right: 0;
}
.snapshotsrc-wrap {
width: 100vw;
height: 100vh;
}
</style>
- 发布:2022-03-16 20:21
- 更新:2022-08-29 11:23
- 阅读:628
产品分类: uniapp/App
PC开发环境操作系统: Windows
PC开发环境操作系统版本号: win10
HBuilderX类型: 正式
HBuilderX版本号: 3.3.13
手机系统: Android
手机系统版本号: Android 10
手机厂商: 华为
手机机型: 华为meta30
页面类型: vue
vue版本: vue2
打包方式: 云端
项目创建方式: HBuilderX
示例代码:
操作步骤:
生成水印后拖动异常跳动
生成水印后拖动异常跳动
预期结果:
正常跟随手指移动
正常跟随手指移动
实际结果:
异常跳动
异常跳动
bug描述:
nvue页面使用live-pusher做自定义相机,动态生成水印后使用touchmove滑动水印在安卓手机上跳动剧烈,ios正常,滑动是动态固定定位top,left控制
1***@qq.com (作者)
有的 这样的数据
{ img: '/static/image/flower.png', moveX: 20, moveY: 80, delShow: false }
2022-03-17 08:56