fix:所有document访问前加typeof守卫,非H5自动fallback系统相机
This commit is contained in:
parent
1ee3a0a274
commit
e6decbb433
@ -1,12 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="cc-page">
|
<view class="cc-page">
|
||||||
<!-- 摄像头预览区(WebRTC) -->
|
<!-- 摄像头预览区 -->
|
||||||
<view class="cc-camera-wrap">
|
<view class="cc-camera-wrap">
|
||||||
<video id="ccVideo" class="cc-video" autoplay playsinline muted></video>
|
<video id="ccVideo" ref="ccVideo" class="cc-video" autoplay playsinline muted v-if="useWebRTC"></video>
|
||||||
<canvas id="ccCanvas" class="cc-canvas" style="display:none;"></canvas>
|
<view class="cc-camera-hint" v-if="!useWebRTC">
|
||||||
<view class="cc-camera-hint" v-if="!ctxReady">
|
<text class="cc-hint-text">点击拍照按钮调用系统相机</text>
|
||||||
<text class="cc-hint-text">{{ hintText }}</text>
|
|
||||||
</view>
|
</view>
|
||||||
|
<canvas id="ccCanvas" ref="ccCanvas" class="cc-canvas" style="display:none;"></canvas>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 已拍照九宫格 -->
|
<!-- 已拍照九宫格 -->
|
||||||
@ -43,43 +43,60 @@
|
|||||||
capturedList: [],
|
capturedList: [],
|
||||||
mediaStream: null,
|
mediaStream: null,
|
||||||
ctxReady: false,
|
ctxReady: false,
|
||||||
hintText: '摄像头启动中...'
|
useWebRTC: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onReady() {
|
onReady() {
|
||||||
this.startCamera()
|
this.checkEnvironment()
|
||||||
},
|
},
|
||||||
onUnload() {
|
onUnload() {
|
||||||
this.stopCamera()
|
this.stopCamera()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
startCamera() {
|
// 检测运行环境
|
||||||
var that = this
|
checkEnvironment() {
|
||||||
this.hintText = '摄像头启动中...'
|
// H5 环境:document 存在且 getUserMedia 可用
|
||||||
try {
|
try {
|
||||||
setTimeout(function() {
|
if (typeof document !== 'undefined' && typeof navigator !== 'undefined' && navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
|
||||||
var video = document.getElementById('ccVideo')
|
this.useWebRTC = true
|
||||||
if (!video) {
|
this.startWebRTC()
|
||||||
that.hintText = '视频组件加载失败'
|
} else {
|
||||||
return
|
this.useWebRTC = false
|
||||||
}
|
this.ctxReady = true
|
||||||
navigator.mediaDevices.getUserMedia({ video: { facingMode: 'environment', width: 1280, height: 720 } })
|
}
|
||||||
.then(function(stream) {
|
} catch (e) {
|
||||||
that.mediaStream = stream
|
this.useWebRTC = false
|
||||||
video.srcObject = stream
|
this.ctxReady = true
|
||||||
video.play()
|
}
|
||||||
that.ctxReady = true
|
},
|
||||||
that.hintText = ''
|
// WebRTC 启动摄像头(H5 环境)
|
||||||
console.log('摄像头已就绪(WebRTC)')
|
startWebRTC() {
|
||||||
})
|
var that = this
|
||||||
.catch(function(err) {
|
try {
|
||||||
console.error('getUserMedia失败:', err)
|
if (typeof document === 'undefined') {
|
||||||
that.hintText = '摄像头访问被拒绝: ' + (err.message || '')
|
this.ctxReady = true
|
||||||
})
|
return
|
||||||
}, 500)
|
}
|
||||||
|
var video = document.getElementById('ccVideo')
|
||||||
|
if (!video) {
|
||||||
|
this.ctxReady = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
navigator.mediaDevices.getUserMedia({ video: { facingMode: 'environment', width: 1280, height: 720 } })
|
||||||
|
.then(function(stream) {
|
||||||
|
that.mediaStream = stream
|
||||||
|
video.srcObject = stream
|
||||||
|
video.play()
|
||||||
|
that.ctxReady = true
|
||||||
|
console.log('WebRTC摄像头已就绪')
|
||||||
|
})
|
||||||
|
.catch(function(err) {
|
||||||
|
console.error('getUserMedia失败:', err)
|
||||||
|
that.ctxReady = true
|
||||||
|
})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('摄像头启动异常:', e)
|
console.error('摄像头启动异常:', e)
|
||||||
this.hintText = '摄像头启动异常'
|
this.ctxReady = true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
stopCamera() {
|
stopCamera() {
|
||||||
@ -96,37 +113,44 @@
|
|||||||
uni.showToast({ title: '最多拍9张', icon: 'none' })
|
uni.showToast({ title: '最多拍9张', icon: 'none' })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 用 canvas 截取 video 帧
|
if (this.useWebRTC && this.mediaStream && this.ctxReady) {
|
||||||
var video = document.getElementById('ccVideo')
|
this.webRTCCapture()
|
||||||
|
} else {
|
||||||
|
this.systemCapture()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// WebRTC 截图
|
||||||
|
webRTCCapture() {
|
||||||
|
if (typeof document === 'undefined') {
|
||||||
|
this.systemCapture()
|
||||||
|
return
|
||||||
|
}
|
||||||
var canvas = document.getElementById('ccCanvas')
|
var canvas = document.getElementById('ccCanvas')
|
||||||
if (!video || !canvas) {
|
var video = document.getElementById('ccVideo')
|
||||||
uni.showToast({ title: '拍照失败', icon: 'none' })
|
if (!canvas || !video) {
|
||||||
|
this.systemCapture()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
canvas.width = video.videoWidth || 1280
|
canvas.width = video.videoWidth || 1280
|
||||||
canvas.height = video.videoHeight || 720
|
canvas.height = video.videoHeight || 720
|
||||||
var ctx = canvas.getContext('2d')
|
var ctx = canvas.getContext('2d')
|
||||||
ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
|
ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
|
||||||
// 转 blob 后生成本地临时文件路径
|
var dataUrl = canvas.toDataURL('image/jpeg', 0.85)
|
||||||
|
this.capturedList.push(dataUrl)
|
||||||
|
},
|
||||||
|
// 系统相机拍照
|
||||||
|
systemCapture() {
|
||||||
var that = this
|
var that = this
|
||||||
canvas.toBlob(function(blob) {
|
uni.chooseImage({
|
||||||
if (!blob) {
|
count: 1,
|
||||||
// fallback: data url
|
sourceType: ['camera'],
|
||||||
var dataUrl = canvas.toDataURL('image/jpeg', 0.85)
|
sizeType: ['original'],
|
||||||
that.capturedList.push(dataUrl)
|
success: function(res) {
|
||||||
return
|
if (res.tempFilePaths && res.tempFilePaths.length > 0) {
|
||||||
}
|
that.capturedList.push(res.tempFilePaths[0])
|
||||||
// 用 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)
|
||||||
@ -136,7 +160,6 @@
|
|||||||
uni.showToast({ title: '请先拍照', icon: 'none' })
|
uni.showToast({ title: '请先拍照', icon: 'none' })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 停止摄像头
|
|
||||||
this.stopCamera()
|
this.stopCamera()
|
||||||
var pages = getCurrentPages()
|
var pages = getCurrentPages()
|
||||||
var prevPage = pages[pages.length - 2]
|
var prevPage = pages[pages.length - 2]
|
||||||
@ -162,6 +185,9 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: #111;
|
background: #111;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
.cc-video {
|
.cc-video {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -172,21 +198,12 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
.cc-camera-hint {
|
.cc-camera-hint {
|
||||||
position: absolute;
|
text-align: center;
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
background: #111;
|
|
||||||
padding: 40rpx;
|
padding: 40rpx;
|
||||||
}
|
}
|
||||||
.cc-hint-text {
|
.cc-hint-text {
|
||||||
color: #999;
|
color: #999;
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
text-align: center;
|
|
||||||
}
|
}
|
||||||
.cc-thumb-bar {
|
.cc-thumb-bar {
|
||||||
background: #1a1a1a;
|
background: #1a1a1a;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user