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进度条效果
Feb 22 HTML / CSS
html5 css3 动态气泡按钮实例演示
Dec 02 HTML / CSS
CSS3+Sprite实现僵尸行走动画特效源码
Jan 27 HTML / CSS
详解CSS3中nth-child与nth-of-type的区别
Jan 05 HTML / CSS
纯CSS3实现扇形动画菜单(简化版)实例源码
Jan 17 HTML / CSS
css3如何绘制一个圆圆的loading转圈动画
Jan 09 HTML / CSS
canvas粒子动画背景的实现示例
Sep 03 HTML / CSS
html5-canvas中使用clip抠出一个区域的示例代码
May 25 HTML / CSS
实例教程 HTML5 Canvas 超炫酷烟花绽放动画实现代码
Nov 05 HTML / CSS
详解移动端Html5页面中1px边框的几种解决方法
Jul 24 HTML / CSS
canvas 绘图时位置偏离的问题解决
Sep 16 HTML / CSS
CSS实现九宫格布局(自适应)的示例代码
Feb 12 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
怎样在UNIX系统下安装php3
2006/10/09 PHP
PHP 和 XML: 使用expat函数(一)
2006/10/09 PHP
比较时间段一与时间段二是否有交集的php函数
2011/05/31 PHP
ThinkPHP和UCenter接口冲突的解决方法
2016/07/25 PHP
Laravel重写用户登录简单示例
2016/10/08 PHP
浅谈PHP的反射API
2017/02/26 PHP
利用Laravel事件系统如何实现登录日志的记录详解
2017/05/20 PHP
php字符串截取函数mb_substr用法实例分析
2019/06/25 PHP
js停止输出代码
2008/07/20 Javascript
一个JavaScript获取元素当前高度的实例
2014/10/29 Javascript
jQuery验证插件validation使用指南
2015/04/21 Javascript
JS与jQuery遍历Table所有单元格内容的方法
2015/12/07 Javascript
vue深入解析之render function code详解
2017/07/18 Javascript
AngularJs ng-change事件/指令的用法小结
2017/11/01 Javascript
使用taro开发微信小程序遇到的坑总结
2019/04/08 Javascript
原生JS实现动态添加新元素、删除元素方法
2019/05/05 Javascript
bootstrap-treeview实现多级树形菜单 后台JSON格式如何组织?
2019/07/26 Javascript
梳理一下vue中的生命周期
2020/12/30 Vue.js
javascript代码实现简易计算器
2021/01/25 Javascript
简单介绍利用TK在Python下进行GUI编程的教程
2015/04/13 Python
初步解析Python下的多进程编程
2015/04/28 Python
Python基于生成器迭代实现的八皇后问题示例
2018/05/23 Python
Python编程图形库之Pillow使用方法讲解
2018/12/28 Python
python根据文章标题内容自动生成摘要的实例
2019/02/21 Python
django将数组传递给前台模板的方法
2019/08/06 Python
Python使用xpath实现图片爬取
2020/09/16 Python
Pycharm配置autopep8实现流程解析
2020/11/28 Python
PyTorch中的拷贝与就地操作详解
2020/12/09 Python
微信浏览器取消缓存的方法
2015/03/28 HTML / CSS
Mio Skincare中文官网:肌肤和身体护理
2016/10/26 全球购物
美国珠宝店:Helzberg Diamonds
2018/10/24 全球购物
2014年应届大学生自我评价
2014/01/09 职场文书
旅游安全协议书
2014/04/21 职场文书
优秀毕业生就业推荐信
2014/05/22 职场文书
银行柜员工作心得体会
2016/01/23 职场文书
使用Python通过企业微信应用给企业成员发消息
2022/04/18 Python