/*
实例化camvas配置参数
config = {
video:{width:Number(scale*4),height:Number(scale*3)},//视频比例4:3
canvasId:'canvas',//画布canvas节点ID
videoId:'v',//video节点ID
imgType:'png',//图片类型,/png|jpeg|bmp|gif/
quality:'1' //图片质量0-1之间
}
*/ window.URL = window.URL || window.webkitURL||window.mozURL || window.msURL; navigator.getUserMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia window.requestAnimationFrame = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame // Integrate navigator.getUserMedia & navigator.mediaDevices.getUserMedia
function getUserMedia (constraints, successCallback, errorCallback) {
if (!constraints || !successCallback || !errorCallback) {return} if (navigator.mediaDevices) {
navigator.mediaDevices.getUserMedia(constraints).then(successCallback, errorCallback)
} else {
navigator.getUserMedia(constraints, successCallback, errorCallback)
}
} //获取摄像头设备源
function getMediaStream() {
var exArray = []; //存储设备源ID
MediaStreamTrack.getSources(function (sourceInfos) {
for (var i = 0; i != sourceInfos.length; ++i) {
var sourceInfo = sourceInfos[i];
//这里会遍历audio,video,所以要加以区分
if (sourceInfo.kind === 'video') {
exArray.push(sourceInfo.id);
}
}
});
return exArray;
} //用户手机端使用后置摄像头
function getMediaConfig() {
if (navigator.getUserMedia) {
if(/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)){
//手机端
return {
'video':
{'optional': [
{'sourceId': getMediaStream()[1] //0为前置摄像头,1为后置
}]
},
'audio':false
}
}else{
return {'video':true,'audio':false}
}
}
else {
alert('Native device media streaming (getUserMedia) not supported in this browser.');
}
} // The function takes a canvas context and a `drawFunc` function.
// `drawFunc` receives two parameters, the video and the time since
// the last time it was called.
function camvas(config) {
var self = this
self.convas = document.getElementById(config.canvasId)
self.ctx = self.convas.getContext('2d');
self.config = config
self.isStop = false; //video节点ID
self.video = document.getElementById(self.config.videoId) //video 显示尺寸
self.video.setAttribute('width', this.config.video.width)
self.video.setAttribute('height', this.config.video.height) //视频流控制句柄
var mediaStreamTrack;
//对外开启视频方法
this.startCamera = function () {
// The callback happens when we are starting to stream the video.
getUserMedia(getMediaConfig(), function(stream) {
// Yay, now our webcam input is treated as a normal video and
// we can start having fun
try {
mediaStreamTrack = typeof stream.stop === 'function' ? stream : stream.getTracks().length==1 ?
stream.getTracks()[0]:stream.getTracks()[1];
if(self.video.mozSrcObject !== undefined){
//Firefox中,video.mozSrcObject最初为null,而不是未定义的,我们可以靠这个来检测Firefox的支持
self.video.mozSrcObject = stream;
}else{
self.video.srcObject = stream;
}
} catch (error) {
self.video.src = window.URL && window.URL.createObjectURL(stream) || stream;
}
self.isStop = false;
self.video.play();
// Let's start drawing the canvas!
// self.recordVideo()
}, function(err){
alert(err);
})
} //录像方法
this.recordVideo = function() {
var self = this
var last = Date.now()
var loop = function() {
// For some effects, you might want to know how much time is passed
// since the last frame; that's why we pass along a Delta time `dt`
// variable (expressed in milliseconds)
var dt = Date.now() - last
self.draw(self.video, dt)
last = Date.now()
requestAnimationFrame(loop)
}
requestAnimationFrame(loop)
}
//停止视频
this.stop = function () {
self.ctx.clearRect(0, 0, self.config.video.width,self.config.video.height);
mediaStreamTrack && mediaStreamTrack.stop();
self.isStop = true;
}
//拍照,base64/image/png
this.drawImage=function (callback) {
if(!self.isStop){
self.ctx.drawImage(self.video,0,0,self.config.video.width,self.config.video.height);
var base64URL = self.convas.toDataURL('image/'+self.config.imgType,self.config.quality);
callback&&callback(base64URL);
}
} //录像数据帧
this.draw = function(video, dt) {
self.ctx.drawImage(video, 0, 0)
}
}
<style>
.camera-control {
position: absolute;
z-index: 10;
left: 0;
right: 0;
bottom: 0;
text-align: center;
padding: 10px;
min-height: 40px;
}
.camera-btn {
cursor: pointer;
border: none;
color: #fff;
padding: 8px 12px;
font-size: 14px;
outline: none;
background-color: rgba(255, 255, 255, 0.3);
transition: all 0.3s;
box-shadow: 0 2px 0 0 rgba(45, 140, 240, 0.8);
margin: 0 5px;
}
.camera-canvas-group {
display: flex;
left: 0;
right: 0;
height: 80px;
}
.camera-canvas-item {
opacity: 0.8;
flex: 1;
max-width: 100px;
height: 100%;
overflow: hidden;
clear: both;
margin-bottom: -1px;
transition: all 0.2s;
position: relative;
}
.camera-canvas-item img {
float: left;
width: 100%;
background-color: #000;
border: 1px solid #fff;
} .camera-canvas-item:hover {
position: relative;
opacity: 1;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.8);
} .camera-canvas-item:hover {}
.camera-btn:hover {
background-color: rgba(45, 140, 240, 0.6);
box-shadow: 0 2px 0 0 rgba(45, 140, 240, 1);
} .camera-btn:active {
background-color: rgba(45, 140, 240, 0.2);
}
.canvas-item-del{
position: absolute;
right: 0px;
font-size: 22px;
color: #ef475d;
cursor: pointer;
}
.camera-show-pc{
background-color:#FFFFFF;margin:0px auto;
}
</style>
<div class="layui-fluid layui-anim" id="camera" lay-title="摄像头测试">
<div class="layui-row">
<div class="layui-card" style="background-color:#1E8AE8;margin: auto auto;">
<div class="layui-card-body">
<div class="layui-row camera-show-pc">
<h1 style="padding: 23px 0px;;font-size: 2.4rem;color: #1E8AE8;font-weight: bold;text-align: center">camera</h1>
<div class="bag_display_flex" style="justify-content: center;">
<div style="position: relative;">
<video id="v" style="background-color: #000000"></video>
<div class="camera-control">
<button type="button" id="stop" class="layui-icon layui-icon-stop camera-btn">关闭</button>
<button type="button" id="start" class="layui-icon layui-icon-triangle-r camera-btn">开始</button>
<button type="button" id="snap" class="layui-icon layui-icon-camera-fill camera-btn">拍照</button>
<button type="button" id="save" class="layui-icon layui-icon-save camera-btn">保存</button>
<button type="button" id="clear" class="layui-icon layui-icon-fonts-clear camera-btn">清空</button>
</div>
</div>
<div>
<canvas id="canvas" style="margin-left: 2px;background-color: #000000"></canvas>
</div>
</div>
<div class="layui-row" style="position: relative">
<div class="camera-canvas-group"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="js/camera/camvas.js"></script>
<script data-th-inline="javascript" type="text/javascript">
layui.use(['jquery'], function () {
var $ = layui.jquery,
$view = $('#camera'),
config={},
myCamvas;
init();
onClick(); function init() {
let scale = 120;//宽高比例倍数
config = {
video:{width:Number(scale*4),height:Number(scale*3)},//4:3
canvasId:'canvas',
videoId:'v',
imgType:'png',
quality:'1' //图片质量0-1之间
};
$('.camera-show-pc').css('width',config.video.width*2+20);
$view.find('#canvas').attr('width',config.video.width);
$view.find('#canvas').attr('height',config.video.height);
//拍照实例化
myCamvas = new camvas(config);
myCamvas.startCamera();
$view.find('#start').hide();
}
function onClick() {
//停止拍照
$view.find('#stop').click(function () {
myCamvas.stop()
$view.find('#stop').hide()
$view.find('#start').show()
})
//启动摄像头
$view.find('#start').click(function () {
myCamvas.startCamera();
$view.find('#stop').show()
$view.find('#start').hide()
})
//拍照
$view.find('#snap').click(function () {
myCamvas.drawImage(function drawImage(base64URL) {
let xsCamera = $('<div></div>').addClass('camera-canvas-item');
xsCamera.append($('<img>').attr('src',base64URL)).append($('<span></span>').addClass('layui-icon layui-icon-close-circle-fill canvas-item-del'));
$('.camera-canvas-group').prepend(xsCamera);
});
})
//清空
$view.find('#clear').click(function () {
$view.find('.camera-canvas-group').empty()
}) //append方式添加节点直接click无效,点击显示大图
$view.find('.camera-canvas-group').on('click','.camera-canvas-item img',function () {
myCamvas.ctx.drawImage(this,0,0,config.video.width,config.video.height)
})
//删除图片
$view.find('.camera-canvas-group').on('click','.camera-canvas-item .canvas-item-del',function () {
//删除父节点元素
$(this).closest('.camera-canvas-item').remove()
})
//保存所有图片到本地
$view.find('#save').click(function () {
let fileName = getFileName();
let el_a = $('<a>');
layui.each($view.find('.camera-canvas-group .camera-canvas-item'),function (k,item) {
let t_filename = fileName+'_'+k+'.'+config.imgType;
downLoad($(this).find('img').attr('src'),t_filename,config.imgType);
})
})
//空格按下拍照
$(document).keypress(function (e) {
e.keyCode===32&&$('#snap').trigger('click');
})
};
//tode
function getFileName() {
let date = new Date();
let fileName = ''+date.getFullYear()+(date.getMonth()<9?+'0':'')
+(date.getMonth()+1) +(date.getDate()<10?+'0':'')+date.getDate()
+date.getHours() +date.getMinutes()+(date.getSeconds()<10?'0':'')+date.getSeconds();
return fileName;
}
function downLoad(dataURL,fileName,fileType) {
var reader = new FileReader();
reader.readAsDataURL(createFile(dataURL));
reader.onload = function (e) {
if ('msSaveOrOpenBlob' in navigator) { // IE,Edge
var base64file = e.target.result + '';
window.navigator.msSaveOrOpenBlob(createFile(base64file.replace('data:' + fileType + ';base64,', ''), fileType), fileName);
} else { // chrome,firefox
var link = document.createElement('a');
link.style.display = 'none';
link.href = e.target.result;
link.setAttribute('download', fileName);
// document.body.appendChild(link);
link.click();
$(link).remove();
}
} /*dataURL = dataURL.replace('image/'+fileType,'image/octet-stream');
var save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
save_link.href = dataURL;
save_link.download = fileName;
$(save_link).click()
var event = document.createEvent('MouseEvents');
event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
save_link.dispatchEvent(event);*/
}; // 解析 BASE64文件内容 for IE,Edge
function createFile(urlData) {
var arr = urlData.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = window.atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], { type: mime });
} });
</script>

浏览器调起摄像头(jquery+layui)的更多相关文章

  1. 在火狐、360等浏览器中,用jquery创建表单并发送的问题

    某些浏览器无法使用js或者jquery直接创建表单并发送,这是由于这些浏览器在提交页面表单时要求页面有完整的标签项即<html><head><title></ ...

  2. input type = file 在部分安卓手机上无法调起摄像头和相册

    移动端H5web 用input type = file 在部分安卓手机上无法调起摄像头拍照,有的也无法访问相册而是直接访问了文档,解决办法是: 加上 accept = "image/*&qu ...

  3. 浏览器调起Hbuilder的APP

           最近用Hbuilder来开发APP,测试各种功能,其中,最近测试到,要用这个浏览器调起APP的功能,我看官网有教程,但是有些可能刚工作没多久,所以,有些地方看不大明白,官方也没细说,所以 ...

  4. jquery layui的巨坑

    jquery layui的巨坑 layui 模块不能写在ajax里 因为 layui只能执行一次 第二次会没效果 再执行需要刷新页面再执行

  5. 深入浏览器兼容 细数jQuery Hooks 属性篇

    关于钩子:http://www.cnblogs.com/aaronjs/p/3387906.html 本章的目的很简单,通过钩子函数更细节的了解浏览器差异与处理方案, 版本是2.0.3所以不兼容ie6 ...

  6. 浏览器下载/导出文件 及jQuery表单提交

    1 比如以下按钮, 用于导出文件,如EXCEL文件. <li> <button class="whiteBg btn2" onclick="doExp( ...

  7. 能跨域和跨浏览器的flashcookie for jquery插件

    对于写网站时需要跨域和跨浏览器的可以看看这个. 引入jquery  和 swfstore.min.js 就可以了,蛮简单好用的,会jquery基础就可以咯. mySwfStore.set('myKey ...

  8. pasteimg浏览器中粘贴图片jQuery插件

    pasteimg是一款可以在浏览器中实现图片粘贴的jQuery插件,兼容Chrome.Firefox.IE11以及其他使用这些内核的浏览器,比如,国内著名的360浏览器. pasteimg可以识别浏览 ...

  9. chrome浏览器模拟手机端:jquery click()点击无效解决方法

    $(".sku-wrap .ok").click(); chrome浏览器模拟手机端,在油猴插件中写JS代码,然后发现click()点击失效. 解决方法:jquery的click( ...

随机推荐

  1. 一gradle创建SSM项目——依赖包

    build.gradle compile:编译时必须. runtime:运行时必须,包括编译时. testCompile:测试编译时必须. testRuntime:测试运行时必须,包括编译时. 注:此 ...

  2. VirtualBox中安装CentOS 7

    1.如下所示图,点击“新建”,创建一个新的虚拟机 2.类型选择Linux,版本选择Red Hat,下一步 3.分配内存大小,电脑8G内存,所以分给虚拟机2G,选择下一步 4.选择“现在创建虚拟硬盘” ...

  3. 《Android程序设计》课程学习

    一.课件内容 2019-2010-1学期课件,点击查看 二.作业相关 上交作业的方法 访问ftp://192.168.42.254:22,登录后找到自己的姓名文件夹,放入作业即可.登录账号为stu2, ...

  4. centeros 安装maven 私服

    1:下载nexus: 下载maven: 2:解压缩 配置maven环境变量 cd /etc/profile MAVEN_HOME=/usr/mavenexport MAVEN_HOMEexport P ...

  5. css--图片整合(精灵图)

    图片整合(精灵图) 精灵图的优点: 减少图片的字节 减少了网页的http请求,从而大大的提高了页面的性能 解决了网页设计师在图片命名上的困扰,只需对一张集合的图片上命名就可以了,不需要对每一个小元素进 ...

  6. NODE升级到V12.X.X

    Node.js 是一个基于Chrome JavaScript运行时的平台,可轻松构建快速,可扩展的网络应用程序.最新版本 node.js yum存储库 由其官方网站维护.使用本教程添加yum存储库,并 ...

  7. Prometheus + Grafana 监控SpringBoot应用

      一.用到的工具 Prometheus Grafana Micrometer Grafana Dashboard (4701)   二.安装和运行Prometheus 官网下载prometheus- ...

  8. iOS---实现简书和知乎的上滑隐藏导航栏下拉显示导航栏效果

    因为自己用简书和知乎比较多,所以对其导航栏的效果比较好奇,自己私下里找资料实现了一下.这个效果的关键点在于下方可供滑动的内容的便宜距离inset的改变,以及滑动的scrollview代理的执行,废话不 ...

  9. nginx配置虚拟主机-端口号区分/域名区分

    Nginx实现虚拟机 可以实现在同一台服务运行多个网站,而且网站之间互相不干扰.同一个服务器可能有一个ip,网站需要使用80端口.网站的域名不同. 区分不同的网站有三种方式:ip区分.端口区分.域名区 ...

  10. [tyvj]P1939玉蟾宫[单调栈]

    [tyvj]P1939 玉蟾宫 ——!x^n+y^n=z^n 背景 有一天,小猫rainbow和freda来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地. 描述 这 ...