码迷,mamicode.com
首页 > Web开发 > 详细

浏览器调起摄像头(jquery+layui)

时间:2019-09-01 18:39:18      阅读:190      评论:0      收藏:0      [点我收藏+]

标签:int   erro   图片   http   anim   source   col   raw   float   

/*
实例化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)

标签:int   erro   图片   http   anim   source   col   raw   float   

原文地址:https://www.cnblogs.com/fushou/p/11442952.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!