1. 先来随便创建一个vue项目
......
2. 拍摄代码最小实现
接着App.vue:
<template>
<div style="width:600px;height:400px">
<video id="video1" src="" style="width:100%;height:100%;background:green" autoplay></video>
</div>
</template>
<script setup>
import {onMounted} from 'vue'
onMounted(() => {
var video=document.getElementById('video1')
navigator.mediaDevices.getUserMedia({ video: true })
.then(stream => {video.srcObject = stream;})
.catch(err => {console.log(err);});
})
</script>
这些代码应该就是进行摄像的最少代码结构了,你直接运行项目打开网页就会发现已经打开相机了:
这些代码都是简单的不要不要的,就不解释了。
但是需要非常注意一个地方就是onMounted这个生命周期钩子函数,为什么要添加这个嘞。
实际上,如果没有onMounted这个生命周期钩子函数,而是直接运行钩子函数里面的代码,你大概率会得到一个报错的结果。
因为里面的代码不能一开始就运行因为dom元素还没有创建完成。这个onMounted函数只是为了保证dom元素都创建出来了,然后才去执行的函数。根据这个思路,你也可以不使用onMounted(前提是这个函数里面的代码不能还没创建完成dom元素就运行)。像下面,我也可以通过按钮来触发:
<template>
<div style="width:600px;height:400px" @click="f1">
<video id="video1" src="" style="width:100%;height:100%;background:green" autoplay></video>
</div>
</template>
<script setup>
function f1(){
var video=document.getElementById('video1')
navigator.mediaDevices.getUserMedia({ video: true })
.then(stream => {video.srcObject = stream;})
.catch(err => {console.log(err);});
}
</script>
另外这里还有个需要注意的地方,那就是video上面的autoplay属性,也可以省略掉,在video.srcObject=stream赋值之后,video.play即可,也就是:
<template>
<div style="width:600px;height:400px" @click="f1">
<video id="video1" src="" style="width:100%;height:100%;background:green"></video>
</div>
</template>
<script setup>
function f1(){
var video=document.getElementById('video1')
navigator.mediaDevices.getUserMedia({ video: true })
.then(stream => {video.srcObject = stream;video.play()})
.catch(err => {console.log(err);});
}
</script>
3. 然后我们开始实现拍照
原理就是,通过canvas来获取video当时的图像,什么时候拍照,就什么时候将vanvas中的图像转成base64格式的数据,再将该base64数据直接赋值给img的src即可。
为此,我们需要去创建一个canvas(因为canvas此时不需要显示出来,同时也不需要占用位置,因此可以设置display属性为none)和一个img(用来放拍摄的结果)。当我们点击按钮(这里直接在img上面的div添加一个@click属性即可,按钮就不添加了)。
<template>
<div style="width:600px;height:400px" @click="f1">
<video id="video1" src="" style="width:100%;height:100%;background:green"></video>
</div>
<div style="width:600px;height:400px;display:none">
<canvas id="canvas1" src="" style="width:600px;height:400px;;display:none"></canvas>
</div>
<div @click="f2" style="width:600px;height:400px;background:green">
<img id="img1" src="" alt="" style="width:100%;height:100%">
</div>
</template>
<script setup>
function f1(){
var video=document.getElementById('video1')
navigator.mediaDevices.getUserMedia({ video: true })
.then(stream => {video.srcObject = stream;video.play()})
.catch(err => {console.log(err);});
}
function f2(){
var video=document.getElementById('video1')
var canvas=document.getElementById('canvas1')
var img=document.getElementById('img1')
console.log("ddd");
canvas.getContext('2d').drawImage(video, 0,0,canvas.width,canvas.height);//内容关联
img.src=canvas.toDataURL('image/png')
}
</script>
这些代码咋一看没啥大问题,但是我们理一下思路,可以发现这个过程中canvas只是起一个中间转换的效果,为什么要给它放到template中嘞?这不合理,不应该把他添加在里面。为此,我们可以在js代码中创建临时的canvas而不是写在template中,用完之后删除canvas即可。代码如下:
<template>
<div style="width:600px;height:400px" @click="f1">
<video id="video1" src="" style="width:100%;height:100%;background:green"></video>
</div>
<div @click="f2" style="width:600px;height:400px;background:green">
<img id="img1" src="" alt="" style="width:100%;height:100%">
</div>
</template>
<script setup>
function f1(){
var video=document.getElementById('video1')
navigator.mediaDevices.getUserMedia({ video: true })
.then(stream => {video.srcObject = stream;video.play()})
.catch(err => {console.log(err);});
}
function f2(){
var video=document.getElementById('video1')
var canvas=document.createElement("canvas")//创建canvas
canvas.style="width:600px;height:400px;;display:none"
var img=document.getElementById('img1')
console.log("ddd");
canvas.getContext('2d').drawImage(video, 0,0,canvas.width,canvas.height);//内容关联
img.src=canvas.toDataURL('image/png')
canvas.remove()//销毁canvas
}
</script>
4. 扩展
从f2中的canvas.toDataURL('image/png'),是一个base64格式的字符串数据,可以直接传给后端来对截图进行处理