/*
实例化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. ES6——Promise

    异步和同步 异步,操作之间没有关系,同时执行多个操作, 代码复杂 同步,同时只能做一件事,代码简单 Promise 对象 用同步的方式来书写异步代码 Promise 让异步操作写起来,像在写同步操作的 ...

  2. [好好学习]在VMware中安装Oracle Enterprise Linux (v5.7) - (3/5)

    进入OEL

  3. Raven2

     Raven2实验 0x01 寻找IP 本机IP:56.130 1. 使用 nmap -sn "ip6"#主机发现(不进行端口扫描) https://cloud.tencent.c ...

  4. PAT考砸有感

    今天下午1点半到4点半是考PAT的时间,考场很安静,大家都在安静地思考,唯一能够听到的是键盘敲击的声音,和几只ACM大牛提前离场的自信的声音,那仿佛就是在说着:哈哈哈,又一次轻松过.考试结束,我还在调 ...

  5. .h与.cpp

    本质上没什么区别. cpp:c plus plus,就表示为c++原文件. .h文件实现的功能是声明.cpp文件中需要使用的变量.函数及宏定义等. .h文件就像是一个接口,具体的实现可以在.cpp中, ...

  6. git@github.com出现Permission denied (publickey)

    上传项目的时候出现Permission denied (publickey)这个问题 解决方案如下: 看本地的.git/config设置的仓库url地址和github使用的链接地址是否一致如下图,如u ...

  7. alert(1) to win 2

    function escape(s) { s = s.replace(/"/g, '\\"'); return '<script>console.log("' ...

  8. Ajax工作原理及C/S与B/S的区别

    工作原理 Ajax 基本上就是把 JavaScript 技术和 XMLHttpRequest 对象放在 Web 表单和服务器之间.当用户填写表单时,数据发送给一些 JavaScript 代码而不是直接 ...

  9. 【leetcode】449. Serialize and Deserialize BST

    题目如下: Serialization is the process of converting a data structure or object into a sequence of bits ...

  10. 做网站用php还是python

    单纯说做网站,显然是php更适合,php是专为web而生,而Python只是可以做web.php也比python更简单,更容易学,对于新手更友好. 从权威技术网站w3techs.com2017年7月2 ...