Html5调用手机摄像头后添加取景框并使用WebUploader上传

标签: html5摄像头  取景框  Webuploader

背景说明

最近同事在项目中遇到了一个问题,在Html5中如何实现如图所示的功能:
在这里插入图片描述

H5调起摄像头并获取图片

使用input标签

代码如下:

<input type="file" accept="image/*;capture=camera">

录制视频或音频也是类似的:

<input type="file" accept="video/*;capture=camcorder">
<input type="file" accept="audio/*;capture=microphone">

但是这种方法不能够添加取景框,调起来的是系统拍照界面,所以无法将取景框蒙在拍照界面。

使用WebRTC

html代码如下:

<div  style="width: 100%; position: fixed; left: 0; bottom: 0; top: 0; right: 0;">

<img src="cover.png" style="width: 100%; height: 100%; position: fixed; left: 0; bottom: 0; top: 0; right: 0;"  />
<button id="snap" style="width: 50px; height: 50px; background: #fff; box-shadow: 0 0  5px #fff; border-radius: 50px; position: fixed; bottom: 20px; left: 50%; margin-left: -25px;" ></button>
<video ></video>
<canvas id="mycanvas"></canvas>

</div>
  • img标签为取景框蒙层
  • button标签是模拟拍照按钮
  • video标签是用来显示摄像头的视频流
  • canvas用来从视频流中抓拍一张图并上传

javascript代码如下:

调起摄像头代码

  // 注意本例需要在HTTPS协议网站中运行,新版本Chrome中getUserMedia接口在http下不再支持。
// 设置事件监听器
window.addEventListener("DOMContentLoaded", function() {
    // 老的浏览器可能根本没有实现 mediaDevices,所以我们可以先设置一个空的对象
    if (navigator.mediaDevices === undefined) {
        navigator.mediaDevices = {};
        alert('1');
    }

    // 一些浏览器部分支持 mediaDevices。我们不能直接给对象设置 getUserMedia 
    // 因为这样可能会覆盖已有的属性。这里我们只会在没有getUserMedia属性的时候添加它。
    if (navigator.mediaDevices.getUserMedia === undefined) {
		navigator.mediaDevices.getUserMedia = function(constraints) {
            alert('2');
			// 首先,如果有getUserMedia的话,就获得它
			var getUserMedia = navigator.getUserMedia ||navigator.webkitGetUserMedia || navigator.mozGetUserMedia;

			// 一些浏览器根本没实现它 - 那么就返回一个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);
			});
		}
    }
    
    var constraints = { audio: false, video: true }; 
    
    navigator.mediaDevices.getUserMedia(constraints)
    .then(function(stream){
        var video = document.querySelector('video');
        // 旧的浏览器可能没有srcObject
        if ("srcObject" in video) {
            video.srcObject = stream;
        } else {
            // 防止在新的浏览器里使用它,应为它已经不再支持了
            video.src = window.URL.createObjectURL(stream);
        }
        video.onloadedmetadata = function(e) {
            video.play();
        };
    })
    .catch(function(err){alert(err.name + ": " + err.message); });
}, false);

添加取景框

取景框是使用一张图片,蒙在了video上边

<img src="cover.png" style="width: 100%; height: 100%; position: fixed; left: 0; bottom: 0; top: 0; right: 0;"  />

抓拍图片并使用WebUploader上传

代码如下:

var snap = document.querySelector('#snap');
    if(snap !== null){
        snap.onclick=function(){
            var canvas = document.querySelector('#mycanvas');
            var ctx = canvas.getContext('2d');
            var video = document.querySelector('video');
            canvas.width = video.videoWidth;
            canvas.height = video.videoHeight;
            canvas.getContext('2d').drawImage(video,0,0);
            canvas.toBlob(function(blob){
                var runtimeForRuid = new WebUploader.Runtime.Runtime();
                console.log(runtimeForRuid.uid);
                blob.name = runtimeForRuid.uid;
                var myFile = new WebUploader.Lib.File(runtimeForRuid.uid,blob);
                var wuFile = new WebUploader.File(myFile);
                uploader.addFile(wuFile);
            });
           
            //var myFile = new File(myBlob,"snap.png");
            
        }
    }

效果

权限提示
在这里插入图片描述拍摄界面
在这里插入图片描述上传到服务器
在这里插入图片描述

踩过的坑

  1. navigator.mediaDevices.getUserMedia需要注意浏览器兼容性
  2. WebUploader上传构造去掉pick参数就可以不显示上传按钮
  3. 运行的时候会提示权限
  4. navigator.mediaDevices.getUserMedia服务器需要用https

参考

MediaDevices.getUserMedia()
Capturing Audio & Video in HTML5
Web Uploader
getUserMedia.js is a cross-browser shim for the getUserMedia() API (a part of WebRTC)

版权声明:本文为richie12原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/richie12/article/details/108667493

智能推荐

基于IP摄像头和opencv使用手机实时人脸检测

基于IP摄像头和opencv使用手机实时人脸检测 工具 一台装有python3.x 一款有摄像头的安卓手机(iphone暂未尝试) 网络 操作步骤 安装opencv 这里我们使用国内镜像,即可快速安装opencv 验证opencv是否安装完成 打开python3 未报错,即为安装成功 安装IP摄像头 给安卓手机安装小米的IP摄像头并更新到最新版,这里我把下载地址放在下面,大家自行下载 链接:htt...

第三方库PNChart的使用

PNChart 是一个强大的带动画的图表库   要是用这个库可以使用pods,也可以直接将库导入项目中,必须引入"PNChart.h"头文件   下面我们来看一下代码!      转载于:https://www.cnblogs.com/aeronfay/articles/4929223.html...

LeetCode刷题笔记(10)-BFS广度优先搜索

LeetCode刷题笔记(10)-BFS广度优先搜索 127、单词接龙 给定两个单词(beginWord 和 endWord)和一个字典,找到从 beginWord 到 endWord 的最短转换序列的长度。转换需遵循如下规则: 每次转换只能改变一个字母。 转换过程中的中间单词必须是字典中的单词。 输入: beginWord = “hit”, endWord = &ldqu...

线性筛选素数的方法及基于线性筛选素数的欧拉函数筛选莫比乌斯函数筛选

欧拉筛法线性求素数 回忆一下经典的埃式筛法求素数。时间复杂度是为O(nloglogn)(我之前一直以为是O(n))O(nloglogn)(我之前一直以为是O(n)) 显然,当一个数是素数的时候,那么他的倍数肯定是合数,筛选标记即可 我们来举个列子 筛选2-10的素数 首先2是素数,然后把其倍数删去,我们标记下删去的次数用一个斜杠表示删去了一次 之后3是素数,继续删去倍数,这个时候发现6被重复删去两...

JEECG 页面多个用户选择器只显示最后一个

在一个页面当中,我们可能会需要有多个的用户选择器进行快速的录入,此时会发现所有的输入都会在最后一个用户选择器的地方显示 查看页面代码当中的ID也是不一致: 查看通过标签生成之后的源码,可以发现所有的用户选择器都会生成一个 点击输入框调用的js方法都是一样的,看到这里也就可以明白为什么都是只有最后一个用户选择输入框当中有数据了。 因此我们对后台当中标签代码生成部分进行改造,让其支持多个用户选择器: ...

猜你喜欢

力扣47 全排列ii 回溯加剪枝

 这题难点在于先排序,然后重复的数字112 used[i-1]= fase 代表之前我用过了,就是我俩 1前面的用过了现在这一个我就直接跳过去    ...

arp协议

arp协议叫做地址解析协议,通常与ip地址共同使用,将ip地址转换成硬件地址(MAC地址)。arp既可以放在网络层,也可以放在数据链路层,因为它做了两层的工作。 当一个主机向另一个主机发送数据报时,通过arp协议,向局域网中发送arp请求,所有在局域网中的主机都可以收到,但会在网络层丢弃,只有一台符合目的ip的主机会发送给源主机arp响应包含自己mac地址,因此源主机就可以向目的主机发送报文。 l...

模拟登陆改版后的知乎(最新版)

今天,想着看看视频,把模拟登陆这一块学习学习,以后弄把梯子,去爬爬FaceBook什么的。就拿知乎练练手吧,可曾想,知乎竟然改版了!!之前的教程书籍对现在的知乎来说,都是扯淡,连页面都找不到了。下面一起谈谈改版后的纸糊的模拟登陆吧。 页面分析 抓包 首先,打开页面:https://www.zhihu.com/signup?next=%2F(登录网址都变了…),F12,输入账号密码(记...

干货分享——比微信域名防封防举报更牛逼的防封方案

从微信兴起到现在,微信的流量就一直居高不下,在淘宝时代和传统的电商时代,只要把广告打出去,别人通过搜索就可以找到我们,所以,移动互联网的到来,在微信爆棚的今天,都想在微信里面推广自己的产品,借力微信,达到客户沉淀,营销宣传,传播影响的目的,可以由于微信种种机制,有人腾讯要维护自身的利益,也有人说是微信要营造一个健康的生态圈,种种限制,比如分享次数过多,域名会被微信拦截屏蔽封杀,还比如微信中的链接不...

mysql的事务提交(java)

个人理解的一个事务:是一个Connection一系列的操作过程,如果是两个Connection连接在操作,那就是两个事务。 事务的前提:数据库的存储引擎是innodb。 事务的目的:保证数据的安全性。 事务安全:  1.自动提交事务:每执行一条sql语句,就同步到数据库中。  2.手动提交事务:执行一系列的sql语句后一起同步到数据库中。 事务的四大特性:  A(at...