|
|
@@ -2,7 +2,8 @@
|
|
|
<view class="zhuapai-drop-container" id="Drop" ref="DropRef" :style="style" @touchmove="touchmove($event)"
|
|
|
@touchstart="touchstart($event)">
|
|
|
<view class="phone-camera-box-zhuapai">
|
|
|
- <camera class="camera" device-position="front" flash="off" style="width: 200px;height: 200px" :class="myClass" @initdone="onVideoSuccess" @error="handleError" @stop="handleStop"></camera>
|
|
|
+ <camera class="camera" device-position="front" flash="off" style="width: 200px;height: 200px"
|
|
|
+ :class="myClass" @initdone="onVideoSuccess" @error="handleError" @stop="handleStop"></camera>
|
|
|
<!-- 用于抓拍切出去传递固定img-->
|
|
|
<img :src="imgUrl" alt="" v-show="false">
|
|
|
</view>
|
|
|
@@ -12,37 +13,46 @@
|
|
|
<view v-show="!showVideo" @click="showVideoBtn" class="shiti-video-show-btn">
|
|
|
<icon :style="{ backgroundImage: 'url(' + iconsArr.videoPlayIcon + ')' }"></icon>
|
|
|
</view>
|
|
|
- <canvas
|
|
|
- canvas-id="frameCanvas"
|
|
|
- id="frameCanvas"
|
|
|
- style="position: absolute;top:9999px;left: 0px;width: 100vw; height: 100vh;z-index:-2"
|
|
|
- ></canvas>
|
|
|
+ <canvas canvas-id="frameCanvas" id="frameCanvas"
|
|
|
+ style="position: absolute;top:9999px;left: 0px;width: 100vw; height: 100vh;z-index:-2"></canvas>
|
|
|
</view>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
- import {ref,onUnmounted,nextTick,computed,onMounted,reactive,getCurrentInstance} from "vue";
|
|
|
+ import {
|
|
|
+ ref,
|
|
|
+ onUnmounted,
|
|
|
+ nextTick,
|
|
|
+ computed,
|
|
|
+ onMounted,
|
|
|
+ reactive,
|
|
|
+ getCurrentInstance
|
|
|
+ } from "vue";
|
|
|
import cacheManager from '@/utils/cacheManager.js';
|
|
|
import * as ksApi from "@/api/kaoshi.js"
|
|
|
import {
|
|
|
getStaticUrl
|
|
|
} from "@/utils/common.js"
|
|
|
-
|
|
|
- import {useZhuapaiStore} from "@/store/zhuapai.js"
|
|
|
- import {getFileUpload} from "@/api/kaoshi.js"
|
|
|
-
|
|
|
+
|
|
|
+ import {
|
|
|
+ useZhuapaiStore
|
|
|
+ } from "@/store/zhuapai.js"
|
|
|
+ import {
|
|
|
+ getFileUpload
|
|
|
+ } from "@/api/kaoshi.js"
|
|
|
+
|
|
|
const zhuapaiStore = useZhuapaiStore();
|
|
|
|
|
|
const imgUrl = '';
|
|
|
|
|
|
const cameraContext = ref(null);
|
|
|
|
|
|
- // 响应式数据
|
|
|
- const frameListener = ref(null)
|
|
|
- const isCapturing = ref(false)
|
|
|
- const capturedImage = ref('')
|
|
|
- const currentFrame = ref(null) // 存储当前帧数据
|
|
|
- const myInstanceR = getCurrentInstance()
|
|
|
+ // 响应式数据
|
|
|
+ const frameListener = ref(null)
|
|
|
+ const isCapturing = ref(false)
|
|
|
+ const capturedImage = ref('')
|
|
|
+ const currentFrame = ref(null) // 存储当前帧数据
|
|
|
+ const myInstanceR = getCurrentInstance()
|
|
|
|
|
|
const DropRef = ref(null);
|
|
|
const DropContainerRef = ref(null);
|
|
|
@@ -60,9 +70,9 @@
|
|
|
});
|
|
|
|
|
|
const iconsArr = reactive({
|
|
|
- noKaoshiImg: '',
|
|
|
- videoCloseIcon: '',
|
|
|
- videoPlayIcon: '',
|
|
|
+ noKaoshiImg: '',
|
|
|
+ videoCloseIcon: '',
|
|
|
+ videoPlayIcon: '',
|
|
|
})
|
|
|
const myClass = computed(() => {
|
|
|
return {
|
|
|
@@ -73,7 +83,8 @@
|
|
|
|
|
|
const emits = defineEmits(['init', 'success', 'error', 'cancel', 'progress'])
|
|
|
|
|
|
- let timer1 = null;
|
|
|
+ let timer1 = null;
|
|
|
+ let timer2 = null;
|
|
|
|
|
|
function noShowVideoBtn() {
|
|
|
showVideo.value = false
|
|
|
@@ -137,21 +148,21 @@
|
|
|
nextTick(() => {
|
|
|
startCamera()
|
|
|
// 设定计时器
|
|
|
- console.log('抓拍设定', zhuapai.value)
|
|
|
- setInterval(() => {
|
|
|
- handleZhua()
|
|
|
- }, zhuapai.value * 60 * 1000)
|
|
|
+ console.log('抓拍设定', zhuapai.value)
|
|
|
+ timer2 = setInterval(() => {
|
|
|
+ handleZhua()
|
|
|
+ }, zhuapai.value * 60 * 1000)
|
|
|
})
|
|
|
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
|
|
|
function startCamera() {
|
|
|
// 请求摄像头权限并获取流
|
|
|
cameraContext.value = uni.createCameraContext();
|
|
|
- startFrameListener()
|
|
|
- }
|
|
|
+ startFrameListener()
|
|
|
+ }
|
|
|
|
|
|
function urlToBase64(url) {
|
|
|
return new Promise((resolve, reject) => {
|
|
|
@@ -174,10 +185,10 @@
|
|
|
}
|
|
|
|
|
|
function getSnapShotImage(data) {
|
|
|
- console.log('转转图片成base64')
|
|
|
+ console.log('转转图片成base64')
|
|
|
urlToBase64(data).then((d1) => {
|
|
|
const imgData = d1.split(';base64,');
|
|
|
-
|
|
|
+
|
|
|
if (!imgData.length) {
|
|
|
console.error('【源 :拍照数据异常,未找到图片二进制数据分割节点: `;base64,`】');
|
|
|
return;
|
|
|
@@ -186,19 +197,19 @@
|
|
|
data: imgData[1],
|
|
|
prefix: 'kaoshi/zhuapai',
|
|
|
suffix: 'png',
|
|
|
-
|
|
|
+
|
|
|
};
|
|
|
- console.log('上传图片')
|
|
|
+ console.log('上传图片')
|
|
|
getFileUpload(opt).then(res => {
|
|
|
const dOption = {
|
|
|
- operId:operId.value,
|
|
|
+ operId: operId.value,
|
|
|
url: res.data
|
|
|
}
|
|
|
ksApi.getClientZhuaPaiUpdate(dOption)
|
|
|
.then(res => {
|
|
|
console.log('【源 : 获取抓拍数据】');
|
|
|
- // 抓拍成功 继续监听
|
|
|
- frameListener.value.start()
|
|
|
+ // 抓拍成功 继续监听
|
|
|
+ frameListener.value.start()
|
|
|
})
|
|
|
.catch(err => {
|
|
|
console.error('源 :抓拍接口异常', err);
|
|
|
@@ -220,9 +231,9 @@
|
|
|
})
|
|
|
})
|
|
|
})
|
|
|
-
|
|
|
+
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
function doZhuaiPai(ImageFile) {
|
|
|
try {
|
|
|
if (zhuapaiStore.status == 0) {
|
|
|
@@ -237,28 +248,28 @@
|
|
|
}
|
|
|
|
|
|
function handleZhua() {
|
|
|
- console.log('抓拍')
|
|
|
- captureSilently();
|
|
|
+ console.log('抓拍')
|
|
|
+ captureSilently();
|
|
|
}
|
|
|
|
|
|
function onVideoSuccess() {
|
|
|
-/* setTimeout(() => {
|
|
|
- // 首次运行进行抓拍一次
|
|
|
- handleZhua();
|
|
|
- }, 3000);*/
|
|
|
+ /* setTimeout(() => {
|
|
|
+ // 首次运行进行抓拍一次
|
|
|
+ handleZhua();
|
|
|
+ }, 3000);*/
|
|
|
}
|
|
|
|
|
|
function onVideoError() {
|
|
|
emits('error')
|
|
|
}
|
|
|
|
|
|
- function handleError() {
|
|
|
- emits('error')
|
|
|
- }
|
|
|
+ function handleError() {
|
|
|
+ emits('error')
|
|
|
+ }
|
|
|
|
|
|
- function handleStop() {
|
|
|
- emits('error')
|
|
|
- }
|
|
|
+ function handleStop() {
|
|
|
+ emits('error')
|
|
|
+ }
|
|
|
|
|
|
// 针对视频通话的监听处理
|
|
|
|
|
|
@@ -282,7 +293,9 @@
|
|
|
isBuffer.value = true;
|
|
|
console.log('onProgress')
|
|
|
// buffer时间增大到3秒 过滤掉后续的onTimeupdate
|
|
|
- timer1 = setTimeout(() => {isBuffer.value = false}, 3000)
|
|
|
+ timer1 = setTimeout(() => {
|
|
|
+ isBuffer.value = false
|
|
|
+ }, 3000)
|
|
|
// 视频中途暂停被占用
|
|
|
stopTimer.value = setTimeout(() => {
|
|
|
emits('progress', false);
|
|
|
@@ -290,134 +303,145 @@
|
|
|
}, 10 * 1000)
|
|
|
}
|
|
|
|
|
|
- /******************************************************/
|
|
|
- // 开始监听相机帧数据
|
|
|
- function startFrameListener(){
|
|
|
- if (!cameraContext.value) {
|
|
|
- uni.showToast({ title: '相机未初始化', icon: 'none' })
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- frameListener.value = cameraContext.value.onCameraFrame((frame) => {
|
|
|
- // 存储当前帧数据,用于后续抓拍
|
|
|
- currentFrame.value = frame
|
|
|
- // console.log('接收帧数据:', frame.width, frame.height)
|
|
|
- })
|
|
|
-
|
|
|
- frameListener.value.start()
|
|
|
- isCapturing.value = true
|
|
|
- // uni.showToast({ title: '开始监控帧数据', icon: 'success' })
|
|
|
- }
|
|
|
-
|
|
|
- // 停止监听帧数据
|
|
|
- function stopFrameListener(){
|
|
|
- if (frameListener.value) {
|
|
|
- frameListener.value.stop()
|
|
|
- frameListener.value = null
|
|
|
- }
|
|
|
- isCapturing.value = false
|
|
|
- // uni.showToast({ title: '已停止监控', icon: 'success' })
|
|
|
- }
|
|
|
- // 静音抓拍核心函数
|
|
|
- async function captureSilently (){
|
|
|
-
|
|
|
- if (!isCapturing.value || !currentFrame.value) {
|
|
|
- uni.showToast({ title: '请先开始监控帧数据', icon: 'none' })
|
|
|
- return
|
|
|
- }
|
|
|
- try {
|
|
|
- console.log('停止前')
|
|
|
- // 临时停止监听以避免数据冲突
|
|
|
- stopFrameListener()
|
|
|
- console.log('开始绘制',)
|
|
|
- // 将帧数据绘制到Canvas并导出为图片
|
|
|
- await drawFrameToCanvas(currentFrame.value).then(url => {
|
|
|
- console.log('获取地址')
|
|
|
- getSnapShotImage(url)
|
|
|
- })
|
|
|
- // 重新开始监听
|
|
|
- startFrameListener()
|
|
|
- } catch (error) {
|
|
|
- console.log('errrrr',error)
|
|
|
- handleError();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 将帧数据绘制到Canvas
|
|
|
- function drawFrameToCanvas(frame) {
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
- try {
|
|
|
- // 确保有有效的帧数据
|
|
|
- if (!frame || !frame.data || !frame.width || !frame.height) {
|
|
|
- reject(new Error('无效的帧数据'))
|
|
|
- return
|
|
|
- }
|
|
|
- // 将ArrayBuffer转换为Uint8ClampedArray[4](@ref)
|
|
|
- const dataArray = new Uint8Array(frame.data)
|
|
|
- const clampedArray = new Uint8ClampedArray(dataArray)
|
|
|
- console.log('clampedArray', clampedArray.length)
|
|
|
- // 使用wx.canvasPutImageData将帧数据绘制到Canvas[4](@ref)
|
|
|
- wx.canvasPutImageData({
|
|
|
- canvasId: 'frameCanvas',
|
|
|
- data: clampedArray,
|
|
|
- x: 0,
|
|
|
- y: 0,
|
|
|
- width: frame.width,
|
|
|
- height: frame.height,
|
|
|
- success: () => {
|
|
|
- // 绘制成功后,将Canvas内容转换为临时图片文件
|
|
|
- wx.canvasToTempFilePath({
|
|
|
- canvasId: 'frameCanvas',
|
|
|
- destWidth: frame.width,
|
|
|
- destHeight: frame.height,
|
|
|
- fileType: 'png',
|
|
|
- quality: 0.7,
|
|
|
- success: (res) => {
|
|
|
- capturedImage.value = res.tempFilePath
|
|
|
- resolve(res.tempFilePath)
|
|
|
- },
|
|
|
- fail: (err) => {
|
|
|
- console.log('5555',err)
|
|
|
- reject(new Error(`生成图片失败: ${err.errMsg}`))
|
|
|
- }
|
|
|
- }, myInstanceR.proxy)
|
|
|
- },
|
|
|
- fail: (err) => {
|
|
|
- console.log('6666',err)
|
|
|
- reject(new Error(`绘制到Canvas失败: ${err.errMsg}`))
|
|
|
- }
|
|
|
- }, myInstanceR.proxy)
|
|
|
-
|
|
|
- } catch (err) {
|
|
|
-
|
|
|
- console.log('ccccc',err)
|
|
|
- }
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- /******************************************************/
|
|
|
-
|
|
|
- onMounted(() => {
|
|
|
+ /******************************************************/
|
|
|
+ // 开始监听相机帧数据
|
|
|
+ function startFrameListener() {
|
|
|
+ if (!cameraContext.value) {
|
|
|
+ uni.showToast({
|
|
|
+ title: '相机未初始化',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ frameListener.value = cameraContext.value.onCameraFrame((frame) => {
|
|
|
+ // 存储当前帧数据,用于后续抓拍
|
|
|
+ currentFrame.value = frame
|
|
|
+ // console.log('接收帧数据:', frame.width, frame.height)
|
|
|
+ })
|
|
|
+
|
|
|
+ frameListener.value.start()
|
|
|
+ isCapturing.value = true
|
|
|
+ // uni.showToast({ title: '开始监控帧数据', icon: 'success' })
|
|
|
+ }
|
|
|
+
|
|
|
+ // 停止监听帧数据
|
|
|
+ function stopFrameListener() {
|
|
|
+ if (frameListener.value) {
|
|
|
+ frameListener.value.stop()
|
|
|
+ frameListener.value = null
|
|
|
+ }
|
|
|
+ isCapturing.value = false
|
|
|
+ // uni.showToast({ title: '已停止监控', icon: 'success' })
|
|
|
+ }
|
|
|
+ // 静音抓拍核心函数
|
|
|
+ async function captureSilently() {
|
|
|
+
|
|
|
+ if (!isCapturing.value || !currentFrame.value) {
|
|
|
+ uni.showToast({
|
|
|
+ title: '请先开始监控帧数据',
|
|
|
+ icon: 'none'
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ console.log('停止前')
|
|
|
+ // 临时停止监听以避免数据冲突
|
|
|
+ stopFrameListener()
|
|
|
+ console.log('开始绘制', )
|
|
|
+ // 将帧数据绘制到Canvas并导出为图片
|
|
|
+ await drawFrameToCanvas(currentFrame.value).then(url => {
|
|
|
+ console.log('获取地址')
|
|
|
+ getSnapShotImage(url)
|
|
|
+ })
|
|
|
+ // 重新开始监听
|
|
|
+ startFrameListener()
|
|
|
+ } catch (error) {
|
|
|
+ console.log('errrrr', error)
|
|
|
+ handleError();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将帧数据绘制到Canvas
|
|
|
+ function drawFrameToCanvas(frame) {
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
+ try {
|
|
|
+ // 确保有有效的帧数据
|
|
|
+ if (!frame || !frame.data || !frame.width || !frame.height) {
|
|
|
+ reject(new Error('无效的帧数据'))
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // 将ArrayBuffer转换为Uint8ClampedArray[4](@ref)
|
|
|
+ const dataArray = new Uint8Array(frame.data)
|
|
|
+ const clampedArray = new Uint8ClampedArray(dataArray)
|
|
|
+ console.log('clampedArray', clampedArray.length)
|
|
|
+ // 使用wx.canvasPutImageData将帧数据绘制到Canvas[4](@ref)
|
|
|
+ wx.canvasPutImageData({
|
|
|
+ canvasId: 'frameCanvas',
|
|
|
+ data: clampedArray,
|
|
|
+ x: 0,
|
|
|
+ y: 0,
|
|
|
+ width: frame.width,
|
|
|
+ height: frame.height,
|
|
|
+ success: () => {
|
|
|
+ // 绘制成功后,将Canvas内容转换为临时图片文件
|
|
|
+ wx.canvasToTempFilePath({
|
|
|
+ canvasId: 'frameCanvas',
|
|
|
+ destWidth: frame.width,
|
|
|
+ destHeight: frame.height,
|
|
|
+ fileType: 'png',
|
|
|
+ quality: 0.7,
|
|
|
+ success: (res) => {
|
|
|
+ capturedImage.value = res.tempFilePath
|
|
|
+ resolve(res.tempFilePath)
|
|
|
+ },
|
|
|
+ fail: (err) => {
|
|
|
+ console.log('5555', err)
|
|
|
+ reject(new Error(`生成图片失败: ${err.errMsg}`))
|
|
|
+ }
|
|
|
+ }, myInstanceR.proxy)
|
|
|
+ },
|
|
|
+ fail: (err) => {
|
|
|
+ console.log('6666', err)
|
|
|
+ reject(new Error(`绘制到Canvas失败: ${err.errMsg}`))
|
|
|
+ }
|
|
|
+ }, myInstanceR.proxy)
|
|
|
+
|
|
|
+ } catch (err) {
|
|
|
+
|
|
|
+ console.log('ccccc', err)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ /******************************************************/
|
|
|
+
|
|
|
+ onMounted(() => {
|
|
|
iconsArr.videoCloseIcon = cacheManager.get('projectImg').video_close_icon;
|
|
|
iconsArr.videoPlayIcon = cacheManager.get('projectImg').video_play_icon;
|
|
|
});
|
|
|
|
|
|
- onUnmounted(() => {
|
|
|
- stopFrameListener()
|
|
|
+ onUnmounted(() => {
|
|
|
+ stopFrameListener()
|
|
|
|
|
|
- if (timer1) {
|
|
|
- clearTimeout(timer1);
|
|
|
- timer1 = null;
|
|
|
- }
|
|
|
- if (stopTimer.value) {
|
|
|
- clearTimeout(stopTimer.value);
|
|
|
- stopTimer.value = null;
|
|
|
- }
|
|
|
- })
|
|
|
+ if (timer1) {
|
|
|
+ clearTimeout(timer1);
|
|
|
+ timer1 = null;
|
|
|
+ }
|
|
|
+ if (stopTimer.value) {
|
|
|
+ clearTimeout(stopTimer.value);
|
|
|
+ stopTimer.value = null;
|
|
|
+ }
|
|
|
+ if (timer2) {
|
|
|
+ clearTimeout(timer2);
|
|
|
+ timer2 = null;
|
|
|
+ }
|
|
|
+ })
|
|
|
|
|
|
defineExpose({
|
|
|
init,
|
|
|
- showVideoBtn
|
|
|
+ showVideoBtn,
|
|
|
+ stopFrameListener
|
|
|
})
|
|
|
</script>
|
|
|
|
|
|
@@ -459,7 +483,7 @@
|
|
|
position: absolute;
|
|
|
top: 0;
|
|
|
|
|
|
- icon{
|
|
|
+ icon {
|
|
|
width: 32rpx;
|
|
|
height: 32rpx;
|
|
|
display: block;
|