fix:连拍改用WebRTC,解决createCameraContext未实现问题

This commit is contained in:
97694732@qq.com 2026-06-06 17:19:11 +08:00
parent 81d559ccb7
commit 1ee3a0a274

View File

@ -1,8 +1,12 @@
<template> <template>
<view class="cc-page"> <view class="cc-page">
<!-- 摄像头预览区 --> <!-- 摄像头预览区WebRTC -->
<view class="cc-camera-wrap"> <view class="cc-camera-wrap">
<camera id="ccCamera" class="cc-camera" device-position="back" flash="off" @error="onCameraError"></camera> <video id="ccVideo" class="cc-video" autoplay playsinline muted></video>
<canvas id="ccCanvas" class="cc-canvas" style="display:none;"></canvas>
<view class="cc-camera-hint" v-if="!ctxReady">
<text class="cc-hint-text">{{ hintText }}</text>
</view>
</view> </view>
<!-- 已拍照九宫格 --> <!-- 已拍照九宫格 -->
@ -37,71 +41,92 @@
data() { data() {
return { return {
capturedList: [], capturedList: [],
ctx: null mediaStream: null,
ctxReady: false,
hintText: '摄像头启动中...'
} }
}, },
onReady() { onReady() {
this.getCameraContext() this.startCamera()
},
onUnload() {
this.stopCamera()
}, },
methods: { methods: {
getCameraContext() { startCamera() {
var that = this
this.hintText = '摄像头启动中...'
try { try {
this.ctx = uni.createCameraContext() setTimeout(function() {
console.log('摄像头上下文:', this.ctx ? '已获取' : '获取失败') var video = document.getElementById('ccVideo')
} catch (e) { if (!video) {
console.error('createCameraContext异常:', e) that.hintText = '视频组件加载失败'
} return
// 15
if (!this.ctx) {
var count = 0
var timer = setInterval(() => {
count++
try {
this.ctx = uni.createCameraContext()
if (this.ctx) {
console.log('摄像头上下文获取成功')
clearInterval(timer)
}
} catch (e) {}
if (count >= 5) {
clearInterval(timer)
console.log('摄像头上下文获取超时')
} }
}, 1000) navigator.mediaDevices.getUserMedia({ video: { facingMode: 'environment', width: 1280, height: 720 } })
.then(function(stream) {
that.mediaStream = stream
video.srcObject = stream
video.play()
that.ctxReady = true
that.hintText = ''
console.log('摄像头已就绪(WebRTC)')
})
.catch(function(err) {
console.error('getUserMedia失败:', err)
that.hintText = '摄像头访问被拒绝: ' + (err.message || '')
})
}, 500)
} catch (e) {
console.error('摄像头启动异常:', e)
this.hintText = '摄像头启动异常'
} }
}, },
onCameraError(e) { stopCamera() {
console.error('摄像头错误:', e) if (this.mediaStream) {
uni.showToast({ title: '摄像头启动失败: ' + (e.detail || ''), icon: 'none' }) var tracks = this.mediaStream.getTracks()
for (var i = 0; i < tracks.length; i++) {
tracks[i].stop()
}
this.mediaStream = null
}
}, },
capturePhoto() { capturePhoto() {
if (this.capturedList.length >= 9) { if (this.capturedList.length >= 9) {
uni.showToast({ title: '最多拍9张', icon: 'none' }) uni.showToast({ title: '最多拍9张', icon: 'none' })
return return
} }
if (!this.ctx) { // canvas video
// var video = document.getElementById('ccVideo')
try { var canvas = document.getElementById('ccCanvas')
this.ctx = uni.createCameraContext() if (!video || !canvas) {
} catch (e) {} uni.showToast({ title: '拍照失败', icon: 'none' })
}
if (!this.ctx) {
uni.showToast({ title: '摄像头未就绪', icon: 'none' })
return return
} }
uni.showLoading({ title: '拍照中...', mask: true }) canvas.width = video.videoWidth || 1280
this.ctx.takePhoto({ canvas.height = video.videoHeight || 720
quality: 'high', var ctx = canvas.getContext('2d')
success: (res) => { ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
uni.hideLoading() // blob
this.capturedList.push(res.tempImagePath) var that = this
}, canvas.toBlob(function(blob) {
fail: (err) => { if (!blob) {
uni.hideLoading() // fallback: data url
console.error('拍照失败:', err) var dataUrl = canvas.toDataURL('image/jpeg', 0.85)
uni.showToast({ title: '拍照失败', icon: 'none' }) that.capturedList.push(dataUrl)
return
} }
}) // FileReader blob dataUrl uni.saveFile
var reader = new FileReader()
reader.onloadend = function() {
var base64 = reader.result
if (base64) {
// base64 data url
that.capturedList.push(base64)
}
}
reader.readAsDataURL(blob)
}, 'image/jpeg', 0.85)
}, },
deletePhoto(idx) { deletePhoto(idx) {
this.capturedList.splice(idx, 1) this.capturedList.splice(idx, 1)
@ -111,6 +136,8 @@
uni.showToast({ title: '请先拍照', icon: 'none' }) uni.showToast({ title: '请先拍照', icon: 'none' })
return return
} }
//
this.stopCamera()
var pages = getCurrentPages() var pages = getCurrentPages()
var prevPage = pages[pages.length - 2] var prevPage = pages[pages.length - 2]
if (prevPage) { if (prevPage) {
@ -136,9 +163,30 @@
overflow: hidden; overflow: hidden;
background: #111; background: #111;
} }
.cc-camera { .cc-video {
width: 100%; width: 100%;
height: 100%; height: 100%;
object-fit: cover;
}
.cc-canvas {
display: none;
}
.cc-camera-hint {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
align-items: center;
justify-content: center;
background: #111;
padding: 40rpx;
}
.cc-hint-text {
color: #999;
font-size: 28rpx;
text-align: center;
} }
.cc-thumb-bar { .cc-thumb-bar {
background: #1a1a1a; background: #1a1a1a;