一般业务也很少接触摄像头,有也是现成的工具库扫个二维码。难得用一次,记录下踩坑。
2.1. input
1
2<input type="file" accept="image/*" capture="camera">
3
4<input type="file" accept="video/*" capture="camcorder">
5
6<input type="file" accept="audio/*" capture="microphone">
这个就不用多说了,缺点就是没办法自定义界面,它是调用的系统原生相机界面。
2.2. mediaDevices
由于我需要自定义界面,就像下面这样:
所以我选择了这个方案,这个api
使用起来其实很简单:
1
2<video id="video" autoplay="autoplay" muted width="200px" height="200px"></video>
3<button onclick="getMedia()">开启摄像头</button>
1async getMedia() {
2
3 const constraints = {
4
5 video: {
6 height: 200,
7 wdith: 200,
8 },
9
10 audio: false
11 };
12 this.video = document.getElementById("video");
13
14
15 this.video.srcObject = await window.navigator.mediaDevices.getUserMedia(constraints);
16
17 this.video.play();
18}
可以看到这个效果。
1
2takePhoto() {
3 const video = document.getElementById("video");
4
5 const canvas = document.getElementById("canvas");
6 const ctx = canvas.getContext('2d');
7 ctx.drawImage(this.video, 0, 0, 300, 300);
8},
9
10stopMedia() {
11
12 const stream = this.video.srcObject;
13 const tracks = stream.getTracks();
14
15 tracks.forEach(function (track) {
16 track.stop();
17 })
18 this.video.srcObject = null;
19}
如果你复制我的代码,在localhost
上肯定能运行,但是你想在手机上试试的时候就会发现很多问题。
3.1. 需要https
由于浏览器的安全设置,除了localhost
和https
连接,你都没办法获取到navigator.mediaDevices
,打印出来是undefined
。如果要在手机上测试,你要么用内网穿透代理一个https
,要么部署在https
域名的服务器上测试。
3.2. 设置前后摄像头
默认是使用user
设备,也就是前摄像头,想要使用后摄像头也是有配置的,
1async getMedia() {
2
3 let constraints = {
4 video: {
5 height: 200,
6 wdith: 200,
7
8 facingMode: { exact: "environment" },
9 },
10 audio: false
11 };
12
13}
3.3. 设置显示区域大小
我的需求是铺满整个设备,所以我想当然的直接把video
样式宽高设置成容器大小:
1#video {
2 width: 100%;
3 height: 100%;
4}
1async getMedia() {
2
3
4 const pageSize = document.querySelector('.page').getBoundingClientRect()
5 let constraints = {
6 video: {
7 height: pageSize.height,
8 width: pageSize.width,
9 facingMode: { exact: "environment" },
10 },
11 audio: false
12 };
13
14}
发现这个视频横着而且没有铺满屏幕。
通过输出video
的信息可以看到,设备返回的视频流宽高是反的:
所以配置换一下就行了:
1 let constraints = {
2 video: {
3 height: pageSize.width,
4 width: pageSize.height,
5 },
6 };
个人笔记记录 2021 ~ 2025