html5调用摄像头功能的实现代码


Posted in HTML / CSS onMay 07, 2018

前言

前些天,线上笔试的时候,发现需要浏览器同意开启摄像头,感觉像是 js 调用的,由于当时笔试,也就没想到这么多问题。今天闲来无事,看了下自己的 todo,发现有这个调用摄像头的todo,才想到?。网上查了一下,果然 js 有调用摄像头的 api,为此自己写一个 demo ,避免忘记。

正文

调用摄像头

一共有两种实现方式,一种是使用navigator.getUserMedia(该特性已经从 Web 标准中删除,虽然一些浏览器目前仍然支持它,但也许会在未来的某个时间停止支持,请尽量不要使用该特性),前面一种已经从 Web 标准中删除,仅为了向后兼容而存在,第二种是使用navigator.mediaDevices.getUserMedia(推荐使用),这两种方法 Safari 貌似都不支持。。。。

第一种方法navigator.getUserMedia用法详见mdn ,代码如下:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>摄像头调用1</title>
</head>
<body>
    <video id="v"></video>
    <script>
        !(function () {
            function userMedia() {
                return navigator.getUserMedia = navigator.getUserMedia ||
                    navigator.webkitGetUserMedia ||
                    navigator.mozGetUserMedia ||
                    navigator.msGetUserMedia || null;
            }
            if (userMedia()) {
                var constraints = {
                    video: true,
                    audio: false
                };
                var media = navigator.getUserMedia(constraints, function (stream) {
                    var v = document.getElementById('v');
                    var url = window.URL || window.webkitURL;
                    v.src = url ? url.createObjectURL(stream) : stream;
                    v.play();
                }, function (error) {
                    console.log("ERROR");
                    console.log(error);
                });
            } else {
                console.log("不支持");
            }
        })();
    </script>
</body>
</html>

第二种方法navigator.mediaDevices.getUserMedia用法详见mdn。navigator.mediaDevices.getUserMedia 其实和第一种差不多,主要第二种返回是一个 Promise 对象,代码如下:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>摄像头调用2</title>
</head>
<body>
    <video id="v"></video>
    <script>
        !(function () {
            // 老的浏览器可能根本没有实现 mediaDevices,所以我们可以先设置一个空的对象
            if (navigator.mediaDevices === undefined) {
                navigator.mediaDevices = {};
            }
            if (navigator.mediaDevices.getUserMedia === undefined) {
                navigator.mediaDevices.getUserMedia = function (constraints) {
                    // 首先,如果有getUserMedia的话,就获得它
                    var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;

                    // 一些浏览器根本没实现它 - 那么就返回一个error到promise的reject来保持一个统一的接口
                    if (!getUserMedia) {
                        return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
                    }

                    // 否则,为老的navigator.getUserMedia方法包裹一个Promise
                    return new Promise(function (resolve, reject) {
                        getUserMedia.call(navigator, constraints, resolve, reject);
                    });
                }
            }
            const constraints = {
                video: true,
                audio: false
            };
            let promise = navigator.mediaDevices.getUserMedia(constraints);
            promise.then(stream => {
                let v = document.getElementById('v');
                // 旧的浏览器可能没有srcObject
                if ("srcObject" in v) {
                    v.srcObject = stream;
                } else {
                    // 防止再新的浏览器里使用它,应为它已经不再支持了
                    v.src = window.URL.createObjectURL(stream);
                }
                v.onloadedmetadata = function (e) {
                    v.play();
                };
            }).catch(err => {
                console.error(err.name + ": " + err.message);
            })
        })();
    </script>
</body>
</html>

拍照

思路是设置一个标志变量 videoPlaying 看看是否 video 有在 play,监听拍照按钮的点击事件,如果videoPlaying 为 true ,使用一个canvas 获取 video 的宽高(默认 canvas 是不显示的),然后使用 canvas 的drawImage,然后使用 canvas 的 toDataURL返回一个 data url,将这个 url,设置在一个 img 标签上即可?

第一种方法navigator.getUserMedia实现代码:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>拍照1</title>
</head>
<body>
    <button id="take">拍照</button>
    <br />
    <video id="v" style="width: 640px;height: 480px;"></video>
    <canvas id="canvas" style="display:none;"></canvas>
    <br />
    <img src="http://placehold.it/640&text=Your%20image%20here%20..." id="photo" alt="photo">
    <script>
        !(function () {
            function userMedia() {
                return navigator.getUserMedia = navigator.getUserMedia ||
                    navigator.webkitGetUserMedia ||
                    navigator.mozGetUserMedia ||
                    navigator.msGetUserMedia || null;
            }
            if (userMedia()) {
                let videoPlaying = false;
                let constraints = {
                    video: true,
                    audio: false
                };
                let video = document.getElementById('v');
                let media = navigator.getUserMedia(constraints, function (stream) {
                    let url = window.URL || window.webkitURL;
                    video.src = url ? url.createObjectURL(stream) : stream;
                    video.play();
                    videoPlaying = true;
                }, function (error) {
                    console.log("ERROR");
                    console.log(error);
                });
                document.getElementById('take').addEventListener('click', function () {
                    if (videoPlaying) {
                        let canvas = document.getElementById('canvas');
                        canvas.width = video.videoWidth;
                        canvas.height = video.videoHeight;
                        canvas.getContext('2d').drawImage(video, 0, 0);
                        let data = canvas.toDataURL('image/webp');
                        document.getElementById('photo').setAttribute('src', data);
                    }
                }, false);
            } else {
                console.log("不支持");
            }
        })();
    </script>
</body>
</html>

第二种navigator.mediaDevices.getUserMedia实现方法:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>拍照2</title>
</head>

<body>
    <button id="take">拍照</button>
    <br />
    <video id="v" style="width: 640px;height: 480px;"></video>
    <canvas id="canvas" style="display:none;"></canvas>
    <br />
    <img src="http://placehold.it/640&text=Your%20image%20here%20..." id="photo" alt="photo">
    <script>
        !(function () {
            // 老的浏览器可能根本没有实现 mediaDevices,所以我们可以先设置一个空的对象
            if (navigator.mediaDevices === undefined) {
                navigator.mediaDevices = {};
            }
            if (navigator.mediaDevices.getUserMedia === undefined) {
                navigator.mediaDevices.getUserMedia = function (constraints) {
                    // 首先,如果有getUserMedia的话,就获得它
                    var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;

                    // 一些浏览器根本没实现它 - 那么就返回一个error到promise的reject来保持一个统一的接口
                    if (!getUserMedia) {
                        return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
                    }

                    // 否则,为老的navigator.getUserMedia方法包裹一个Promise
                    return new Promise(function (resolve, reject) {
                        getUserMedia.call(navigator, constraints, resolve, reject);
                    });
                }
            }
            const constraints = {
                video: true,
                audio: false
            };
            let videoPlaying = false;
            let v = document.getElementById('v');
            let promise = navigator.mediaDevices.getUserMedia(constraints);
            promise.then(stream => {
                // 旧的浏览器可能没有srcObject
                if ("srcObject" in v) {
                    v.srcObject = stream;
                } else {
                    // 防止再新的浏览器里使用它,应为它已经不再支持了
                    v.src = window.URL.createObjectURL(stream);
                }
                v.onloadedmetadata = function (e) {
                    v.play();
                    videoPlaying = true;
                };
            }).catch(err => {
                console.error(err.name + ": " + err.message);
            })
            document.getElementById('take').addEventListener('click', function () {
                if (videoPlaying) {
                    let canvas = document.getElementById('canvas');
                    canvas.width = v.videoWidth;
                    canvas.height = v.videoHeight;
                    canvas.getContext('2d').drawImage(v, 0, 0);
                    let data = canvas.toDataURL('image/webp');
                    document.getElementById('photo').setAttribute('src', data);
                }
            }, false);
        })();
    </script>
</body>
</html>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

HTML / CSS 相关文章推荐
css3高级选择器使用方法
Dec 02 HTML / CSS
CSS3 text-shadow实现文字阴影效果
Feb 24 HTML / CSS
HTML5+CSS3实例 :canvas 模拟实现电子彩票刮刮乐代码
Dec 30 HTML / CSS
CSS3 分类菜单效果
May 27 HTML / CSS
css3一个简易的 LED 数字时钟实现方法
Jan 15 HTML / CSS
html5中canvas学习笔记2-判断浏览器是否支持canvas
Jan 06 HTML / CSS
HTML5之WebGL 3D概述(下)—借助类库开发及框架介绍
Jan 31 HTML / CSS
canvas探照灯效果的示例代码
Nov 30 HTML / CSS
HTML如何让IMG自动适应DIV容器大小的实现方法
Feb 25 HTML / CSS
详解HTML5常用的语义化标签
Sep 27 HTML / CSS
在HTML中引入CSS的几种方式介绍
Dec 06 HTML / CSS
css让页脚保持在底部位置的四种方案
Jul 23 HTML / CSS
探究 canvas 绘图中撤销(undo)功能的实现方式详解
May 17 #HTML / CSS
详解canvas在圆弧周围绘制文本的两种写法
May 22 #HTML / CSS
HTML5 device access 设备访问详解
May 24 #HTML / CSS
html5-canvas中使用clip抠出一个区域的示例代码
May 25 #HTML / CSS
基于 HTML5 的 WebGL 3D 版俄罗斯方块的示例代码
May 28 #HTML / CSS
HTML5探秘:用requestAnimationFrame优化Web动画
Jun 03 #HTML / CSS
html5触摸事件判断滑动方向的实现
Jun 05 #HTML / CSS
You might like
CodeIgniter扩展核心类实例详解
2016/01/20 PHP
类似GMAIL的Ajax信息反馈显示
2010/02/16 Javascript
JavaScript 基础篇之运算符、语句(二)
2012/04/07 Javascript
详解JavaScript中的表单验证
2015/06/16 Javascript
使用JQuery实现Ctrl+Enter提交表单的方法
2015/10/22 Javascript
jquery实时获取时间的简单实例
2017/01/26 Javascript
JavaScript实现简单评论功能
2017/08/17 Javascript
微信小程序使用picker实现时间和日期选择框功能【附源码下载】
2017/12/11 Javascript
vue单个组件实现无限层级多选菜单功能
2018/04/10 Javascript
Javascript数组方法reduce的妙用之处分享
2019/06/10 Javascript
[00:35]DOTA2上海特级锦标赛 Newbee战队宣传片
2016/03/03 DOTA
django之常用命令详解
2016/06/30 Python
python 调用c语言函数的方法
2017/09/29 Python
Tensorflow 自带可视化Tensorboard使用方法(附项目代码)
2018/02/10 Python
对python中Librosa的mfcc步骤详解
2019/01/09 Python
python实现给微信指定好友定时发送消息
2019/04/29 Python
Python列表的切片实例讲解
2019/08/20 Python
python3 selenium自动化 下拉框定位的例子
2019/08/23 Python
Python3之字节串bytes与字节数组bytearray的使用详解
2019/08/27 Python
解决pyinstaller 打包exe文件太大,用pipenv 缩小exe的问题
2020/07/13 Python
Python3+PyCharm+Django+Django REST framework配置与简单开发教程
2021/02/16 Python
使用HTML5和CSS3制作一个模态框的示例
2018/03/07 HTML / CSS
英国安全产品购物网站:The Safe Shop
2017/03/20 全球购物
精选奢华:THE LIST
2019/09/05 全球购物
手工制作的意大利皮革运动鞋:KOIO
2020/01/05 全球购物
学前教育专业毕业生自荐信
2013/10/03 职场文书
现金会计岗位职责
2013/12/05 职场文书
幼儿园春游活动方案
2014/01/19 职场文书
前处理组长岗位职责
2014/03/01 职场文书
《鲁班和橹板》教学反思
2014/04/27 职场文书
校庆口号
2014/06/20 职场文书
英语三分钟演讲稿
2014/08/19 职场文书
乡镇党委书记第三阶段个人整改措施
2014/09/16 职场文书
2015年财务工作总结范文
2015/03/31 职场文书
2016先进工作者事迹材料
2016/02/25 职场文书
导游词之扬州大明寺
2019/10/09 职场文书