IOS 和Android H5 打开摄像头拍照 使用navigator.MediaDevices.getUserMedia() 拍照
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.10/dist/vue.js"></script>
<style>
*{
margin:0;padding: 0;
}
.video-wrap {
overflow: hidden;
width: 30vw;
height: 45vw;
border-radius: 100%;
display: flex;
justify-content: center;
align-items: center;
position: relative;
z-index: 3;
background-color: #ccc;
}
.pic_video {
width: 60vw;
height: 60vw;
transform: rotateY(180deg);
z-index: 6;
position: relative;
}
.buddon {
display: flex;
}
.warm_title2 {
background-color: rgb(150, 150, 231);
color: #fff;
width: 100px;
height: 40px;
line-height: 40px;
text-align: center;
margin-right: 10px;
}
#canvas {
height: 40vw;
transform: rotateY(180deg);
display: none;
}
img {
transform: rotateY(180deg);
}
.flex{
display: flex;
justify-content: center;
margin-top:20px
}
.center{
margin:0 auto;
}
#video{
mix-blend-mode: normal;
outline: -webkit-focus-ring-color auto 0px;
}
</style>
</head>
<body>
<div id="app">
<div class="buddon flex" v-if="imginfo ==''">
<div class="warm_title2" @click='moveToCameraAVG()'>打开摄像头</div>
<div @click='captureAvg' class="warm_title2">拍照</div>
</div>
<div class="buddon flex" v-else>
<div @click='reloadPage' class="warm_title2">重新拍照</div>
</div>
<div v-if="imginfo!==''" class="flex">
<img :src="imginfo" />
</div>
<div class="flex" v-else>
<div class="video-wrap" >
<video id="video" class="pic_video" playsinline autoplay x5-video-player-type="h5"></video>
</div>
</div>
<canvas id="canvas" class="canvas_pic" style='margin: 0;padding: 0;'></canvas>
<!-- <div>
img绘制: <img v-if="imginfo!==''" :src="imginfo" />
</div>
<div>
canvas绘制 : <canvas id="canvas" class="canvas_pic" style='margin: 0;padding: 0;'></canvas>
</div> -->
</div>
</body>
<script src="./jquery.js"></script>
<script>
new Vue({
el: '#app',
data() {
return {
imginfo: ''
}
},
methods: {
// 头像相机
moveToCameraAVG() {
var self = this;
if (navigator.mediaDevices === undefined) {
navigator.mediaDevices = {};
}
if (navigator.mediaDevices.getUserMedia === undefined) {
navigator.mediaDevices.getUserMedia = function (constraints) {
var getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || navigator.oGetUserMedia;
if (!getUserMedia) {
return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
}
return new Promise(function (resolve, reject) {
getUserMedia.call(navigator, constraints, resolve, reject);
});
}
}
if (window.stream) {
window.stream.getTracks().forEach(track => {
track.stop();
});
}
var constraints = window.constraints = {
audio: false,
video: {
sourceId: 'default',
facingMode: { exact: "user" }
}
};
navigator.mediaDevices.getUserMedia(constraints)
.then(function (stream) {
var video = document.getElementById('video');
try {
window.stream = stream;
video.srcObject = stream;
} catch (error) {
video.src = window.URL.createObjectURL(stream);
}
self.localMediaStream = stream;
video.play();
})
.catch(function (err) {
alert(err.name + ": " + err.message);
});
},
imageToCircle(picUrl) {
let radius, diameter, canvas, ctx;
let img = new Image()
img.setAttribute('crossOrigin', 'anonymous'); // 解决图片跨域访问失败
img.src = picUrl
var video = document.getElementById('video');
return new Promise((reslove) => {
img.addEventListener("load", () => {
let height = $('.video-wrap').height()
let width = $('.video-wrap').width()
radius = width / 2;
let canvas = document.createElement('canvas');
if (!canvas.getContext) { // 判断浏览器是否支持canvas,如果不支持在此处做相应的提示
console.log('您的浏览器版本过低,暂不支持。');
return false;
}
canvas.width = width;
canvas.height = height;
ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, width, height);
// 描边
ctx.save(); //save和restore可以保证样式属性只运用于该段canvas元素
ctx.strokeStyle = '#ffffff'; //设置边线的颜色
ctx.lineWidth = 0;
ctx.beginPath(); //开始路径
//ctx.ellipse(radius, radius, radius - 5, 0, Math.PI * 2); //画一个整圆.
const radiusX = width / 2
const radiusY = height / 2
ctx.ellipse(radiusX, radiusY, radiusX, radiusY, 0, 0, Math.PI * 2, true)
// 参数(从左到右):
// (起点x,起点y,半径x,半径y,旋转的角度,起始角,结果角,顺时针还是逆时针)
ctx.stroke();
//绘制边线
// 截圆形图
ctx.save();
ctx.beginPath();
ctx.ellipse(radiusX, radiusY, radiusX, radiusY, 0, 0, Math.PI * 2, true)
ctx.clip();
const videoRatio = video.videoHeight / video.videoWidth // 原视频比例
const domHeight = video.offsetHeight // 元素宽高
const domWidth = video.offsetWidth
let realW = 0, realH = 0;
if (domHeight / domWidth >= videoRatio) { // 宽度占满,计算高度
realW = domWidth
realH = domWidth * videoRatio
} else { // 高度占满,计算宽度
realH = domHeight
realW = domHeight / videoRatio
}
let x = realW - width, y = realH - height, swidth = width, sheight = height
ctx.drawImage(img, x / 2, y / 2, swidth, sheight, 0, 0, swidth, height);
ctx.restore();
// toDataURL()是canvas对象的一种方法,用于将canvas对象转换为base64位编码
let dataURL = canvas.toDataURL('image/png');
reslove(dataURL)
}, false)
})
},
//停止摄像机
stopCapture: function () {
var video = document.getElementById('video');
if (!video.srcObject) return
let stream = video.srcObject
let tracks = stream.getTracks();
tracks.forEach(track => {
track.stop()
})
},
// 头像照片
async captureAvg() {
var vm = this;
var video = document.getElementById('video');
var canvas = document.getElementById('canvas'), ctx = canvas.getContext('2d')
const videoRatio = video.videoHeight / video.videoWidth // 原视频比例
const domHeight = video.offsetHeight // 元素宽高
const domWidth = video.offsetWidth
let realW = 0, realH = 0;
if (domHeight / domWidth >= videoRatio) { // 宽度占满,计算高度
realW = domWidth
realH = domWidth * videoRatio
} else { // 高度占满,计算宽度
realH = domHeight
realW = domHeight / videoRatio
}
CWidth = realW,
CHeight = realH;//获取屏幕大小让canvas自适应
canvas.width = CWidth;
canvas.height = realH;
if (vm.localMediaStream) {
ctx.drawImage(video, 0, 0, CWidth, CHeight);
var dataURL = canvas.toDataURL('image/jpeg'); //dataURL = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA'
const roundUrl = await this.imageToCircle(canvas.toDataURL('image/png'));
vm.imginfo = roundUrl;
// 停止摄像机
video.pause();
this.stopCapture();
}
},
reloadPage(){
location.reload()
}
}
})
</script>
</html>
人活着,最重要的就是开心