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 12 HTML / CSS
CSS3的resize属性使用初探
Sep 27 HTML / CSS
CSS中越界问题的经典解决方案【推荐】
Apr 19 HTML / CSS
CSS3中的transform属性进行2D和3D变换的基本用法
May 12 HTML / CSS
让IE支持HTML5的方法
Dec 11 HTML / CSS
html5 worker 实例(一) 为什么测试不到效果
Jun 24 HTML / CSS
html5本地存储之localstorage 、本地数据库、sessionStorage简单使用示例
May 08 HTML / CSS
html5+css3气泡组件的实现
Nov 21 HTML / CSS
用html5的canvas和JavaScript创建一个绘图程序的简单实例
Jul 06 HTML / CSS
老生常谈 使用 CSS 实现三角形的技巧(多种方法)
Apr 13 HTML / CSS
详解使用 CSS prefers-* 规范提升网站的可访问性与健壮性
May 25 HTML / CSS
table设置超出部分隐藏,鼠标移上去显示全部内容的方法
Dec 24 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
PHP 杂谈《重构-改善既有代码的设计》之三 重新组织数据
2012/04/09 PHP
基于PHP一些十分严重的缺陷详解
2013/06/03 PHP
php使用base64加密解密图片示例分享
2014/01/20 PHP
php中有关字符串的4个函数substr、strrchr、strstr、ereg介绍和使用例子
2014/04/24 PHP
PHP 实现字符串翻转(包含中文汉字)的实现代码
2017/04/01 PHP
JS backgroundImage控制
2009/05/19 Javascript
突发奇想的一个jquery插件
2010/11/19 Javascript
JQuery学习笔录 简单的JQuery
2012/04/09 Javascript
JQuery入门——用one()方法绑定事件处理函数(仅触发一次)
2013/02/05 Javascript
JS中令人发指的valueOf方法介绍
2013/02/22 Javascript
JS针对浏览器窗口关闭事件的监听方法集锦
2016/06/24 Javascript
如何解决IONIC页面底部被遮住无法向上滚动问题
2016/09/06 Javascript
JavaScript中捕获/阻止捕获、冒泡/阻止冒泡方法
2016/12/07 Javascript
jquery设置css样式的多种方法(总结)
2017/02/21 Javascript
原生js 封装get ,post, delete 请求的实例
2017/08/11 Javascript
JS+Canvas绘制动态时钟效果
2017/11/10 Javascript
vue.js2.0点击获取自己的属性和jquery方法
2018/02/23 jQuery
解决Vue中引入swiper,在数据渲染的时候,发生不滑动的问题
2018/09/27 Javascript
通过实例了解js函数中参数的传递
2019/06/15 Javascript
vue项目中实现缓存的最佳方案详解
2019/07/11 Javascript
聊聊Vue中provide/inject的应用详解
2019/11/10 Javascript
javascript canvas检测小球碰撞
2020/04/17 Javascript
Python中的高级数据结构详解
2015/03/27 Python
在Django框架中编写Context处理器的方法
2015/07/20 Python
Python的净值数据接口调用示例分享
2016/03/15 Python
TensorFlow损失函数专题详解
2018/04/26 Python
将python文件打包成EXE应用程序的方法
2019/05/22 Python
把django中admin后台界面的英文修改为中文显示的方法
2019/07/26 Python
Python进程间通信 multiProcessing Queue队列实现详解
2019/09/23 Python
python如何解析复杂sql,实现数据库和表的提取的实例剖析
2020/05/15 Python
巴西独家产品和现场演示购物网站:Shoptime
2019/07/11 全球购物
人力管理专业毕业生求职信
2014/02/27 职场文书
美德少年事迹材料500字
2014/08/19 职场文书
2014年体育工作总结
2014/11/24 职场文书
迟到检讨书
2015/01/26 职场文书
大学生敬老院活动总结
2015/05/07 职场文书