JS打开摄像头并截图上传示例


Posted in Javascript onFebruary 18, 2017

直入正题,JS打开摄像头并截图上传至后端的一个完整步骤

1. 打开摄像头主要用到getUserMedia方法,然后将获取到的媒体流置入video标签

2. 截取图片主要用到canvas绘图,使用drawImage方法将video的内容绘至canvas中

3. 将截取的内容上传至服务器,将canvas中的内容转为base64格式上传,后端(PHP)通过file_put_contents将其转为图片

JS打开摄像头并截图上传示例

要注意的是,在chrome以外的浏览器中,使用摄像头或多或少会出现一些问题,可能也是老问题了,所以以下代码主要基于chrome使用

比如在最新版FireFox中的报错,不知为啥

JS打开摄像头并截图上传示例

JS打开摄像头并截图上传示例

1. 打开摄像头

getUserMedia 有新版本和旧版本两种,建议使用新版本

旧版本位于navigator 对象下,根据浏览器不同有所不同

// 获取媒体方法(旧方法)
  navigator.getMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMeddia || navigator.msGetUserMedia;
if (navigator.getMedia) {
    navigator.getMedia({
      video: true
    }, function(stream) {
      mediaStreamTrack = stream.getTracks()[0];

      video.src = (window.URL || window.webkitURL).createObjectURL(stream);
      video.play();
    }, function(err) {
      console.log(err);
    });
  }

第一个参数中指示需要使用视频(video)或音频(audio)。

第二个参数中指示调用成功后的回调,其中带一个参数(MediaStream),在旧版本中可以直接通过调用MediaStream.stop() 来关闭摄像头,不过在新版之中已废弃。需要使用MediaStream.getTracks()[index].stop() 来关闭相应的Track

第三个参数指示调用失败后的回调

新版本位于navigator.mediaDevices 对象下

if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
    navigator.mediaDevices.getUserMedia({
      video: true,
      audio: true
    }).then(function(stream) {
      console.log(stream);

      mediaStreamTrack = typeof stream.stop === 'function' ? stream : stream.getTracks()[1];

      video.src = (window.URL || window.webkitURL).createObjectURL(stream);
      video.play();
    }).catch(function(err) {
      console.log(err);
    })
  }

与旧版类似,不过该方法返回了一个Promise对象,可以使用then和catch表示成功与失败的回调

需要注意的是,MediaStream.getTracks() 返回的Tracks数组是按第一个参数倒序排列的

比如现在定义了

{
  video: true,
  audio: true
}

想关闭摄像头,就需要调用MediaStream.getTracks()[1].stop();

同理,0对应于audio的track

使用createObjectURL 将MediaStream写入video标签,就能够存储实时的媒体流数据(也可以方便的实时查看画面)

旧版本中webkitURL 对象以不被支持,需要使用URL对象

<video width="200" height="150"></video>
  <canvas width="200" height="150"></canvas>

  <p>
    <button id="snap">截取图像</button>
    <button id="close">关闭摄像头</button>
    <button id="upload">上传图像</button>
  </p>

  <img id="uploaded" width="200" height="150" />

2. 截取图像

将内容写入即可

// 截取图像
  snap.addEventListener('click', function() {
    context.drawImage(video, 0, 0, 200, 150);
  }, false);

3. 关闭摄像头

// 关闭摄像头
  close.addEventListener('click', function() {
    mediaStreamTrack && mediaStreamTrack.stop();
  }, false);

4. 上传截取的图像

canvas.toDataURL('image/png')

// 上传截取的图像
  upload.addEventListener('click', function() {
    jQuery.post('/uploadSnap.php', {
      snapData: canvas.toDataURL('image/png')
    }).done(function(rs) {
      rs = JSON.parse(rs);

      console.log(rs);

      uploaded.src = rs.path;
    }).fail(function(err) {
      console.log(err);
    });
  }, false);

而这里的后端(PHP)则将获取的内容转换成图像文件保存

需要注意的是,要将base64的头部信息字段去掉再保存,否则似乎图像是损坏无法打开滴

<?php

  $snapData = $_POST['snapData'];
  $snapData = str_replace('data:image/png;base64,', '', $snapData);
  // $snapData = str_replace(' ', '+', $snapData);

  $img = base64_decode($snapData);

  $uploadDir = 'upload/';
  $fileName = date('YmdHis', time()) . uniqid();

  if (!(file_put_contents($uploadDir . $fileName, $img))) {
    echo json_encode(array('code' => 500, 'msg' => '文件上传失败'));
  } else {
    echo json_encode(array('code' => 200, 'msg' => '文件上传成功', 'path' => $uploadDir . $fileName));
  }

?>

完整JS代码

<script type="text/javascript" src="jquery.js"></script>
  <script type="text/javascript">
  function $(elem) {
    return document.querySelector(elem);
  }

  // 获取媒体方法(旧方法)
  navigator.getMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMeddia || navigator.msGetUserMedia;

  var canvas = $('canvas'),
    context = canvas.getContext('2d'),
    video = $('video'),
    snap = $('#snap'),
    close = $('#close'),
    upload = $('#upload'),
    uploaded = $('#uploaded'),
    mediaStreamTrack;

  // 获取媒体方法(新方法)
  // 使用新方法打开摄像头
  if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
    navigator.mediaDevices.getUserMedia({
      video: true,
      audio: true
    }).then(function(stream) {
      console.log(stream);

      mediaStreamTrack = typeof stream.stop === 'function' ? stream : stream.getTracks()[1];

      video.src = (window.URL || window.webkitURL).createObjectURL(stream);
      video.play();
    }).catch(function(err) {
      console.log(err);
    })
  }
  // 使用旧方法打开摄像头
  else if (navigator.getMedia) {
    navigator.getMedia({
      video: true
    }, function(stream) {
      mediaStreamTrack = stream.getTracks()[0];

      video.src = (window.URL || window.webkitURL).createObjectURL(stream);
      video.play();
    }, function(err) {
      console.log(err);
    });
  }

  // 截取图像
  snap.addEventListener('click', function() {
    context.drawImage(video, 0, 0, 200, 150);
  }, false);

  // 关闭摄像头
  close.addEventListener('click', function() {
    mediaStreamTrack && mediaStreamTrack.stop();
  }, false);

  // 上传截取的图像
  upload.addEventListener('click', function() {
    jQuery.post('/uploadSnap.php', {
      snapData: canvas.toDataURL('image/png')
    }).done(function(rs) {
      rs = JSON.parse(rs);

      console.log(rs);

      uploaded.src = rs.path;
    }).fail(function(err) {
      console.log(err);
    });
  }, false);

  </script>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
将HTML自动转为JS代码
Jun 26 Javascript
小议Function.apply()之二------利用Apply的参数数组化来提高 JavaScript程序性能
Nov 30 Javascript
在vs2010中调试javascript代码方法
Feb 11 Javascript
jQuery获取checkboxlist的value值的方法
Sep 27 Javascript
JS组件Bootstrap Table表格行拖拽效果实现代码
Aug 27 Javascript
基于JavaScript实现轮播图原理及示例
Apr 10 Javascript
jQuery Validate格式验证功能实例代码(包括重名验证)
Jul 18 jQuery
Node.JS中快速扫描端口并发现局域网内的Web服务器地址(80)
Sep 18 Javascript
jQuery结合jQuery.cookie.js插件实现换肤功能示例
Oct 14 jQuery
解决jquery的ajax调取后端数据成功却渲染失败的问题
Aug 08 jQuery
Vue如何基于es6导入外部js文件
May 15 Javascript
实例讲解React 组件
Jul 07 Javascript
Android中Okhttp3实现上传多张图片同时传递参数
Feb 18 #Javascript
AngularJS表单提交实例详解
Feb 18 #Javascript
JS实现控制图片显示大小的方法【图片等比例缩放功能】
Feb 18 #Javascript
JS实现数组去重复值的方法示例
Feb 18 #Javascript
bootstarp modal框居中显示的实现代码
Feb 18 #Javascript
JS实现本地存储信息的方法(基于localStorage与userData)
Feb 18 #Javascript
JS表单数据验证的正则表达式(常用)
Feb 18 #Javascript
You might like
Zend Guard一些常见问题解答
2008/09/11 PHP
php类的定义与继承用法实例
2015/07/07 PHP
关于Yii中模型场景的一些简单介绍
2019/09/22 PHP
Jquery实现列表(隔行换色,全选,鼠标滑过当前行)效果实例
2013/06/09 Javascript
Jquery中的层次选择器与find()的区别示例介绍
2014/02/20 Javascript
jQuery中:only-child选择器用法实例
2015/01/03 Javascript
javascript合并表格单元格实例代码
2016/01/03 Javascript
js弹出窗口返回值的简单实例
2016/05/28 Javascript
NodeJs读取JSON文件格式化时的注意事项
2016/09/25 NodeJs
Vue.js计算属性computed与watch(5)
2016/12/09 Javascript
基于JS对象创建常用方式及原理分析
2017/06/28 Javascript
详解基于vue-cli配置移动端自适应
2018/01/13 Javascript
JavaScript实现简单的隐藏式侧边栏功能示例
2018/08/31 Javascript
ionic3双击返回退出应用的方法
2019/09/17 Javascript
使用p5.js实现动态GIF图片临摹重现
2019/10/23 Javascript
详解VUE中的插值( Interpolation)语法
2020/10/18 Javascript
深入理解Python中的元类(metaclass)
2015/02/14 Python
python类和函数中使用静态变量的方法
2015/05/09 Python
用python实现简单EXCEL数据统计的实例
2017/01/24 Python
Python编程之黑板上排列组合,你舍得解开吗
2017/10/30 Python
Python+Turtle动态绘制一棵树实例分享
2018/01/16 Python
详解python调用cmd命令三种方法
2019/07/08 Python
python使用Pandas库提升项目的运行速度过程详解
2019/07/12 Python
python机器学习包mlxtend的安装和配置详解
2019/08/21 Python
Python 中的 import 机制之实现远程导入模块
2019/10/29 Python
python中Lambda表达式详解
2019/11/20 Python
在python3中使用shuffle函数要注意的地方
2020/02/28 Python
matplotlib制作雷达图报错ValueError的实现
2021/01/05 Python
Marks & Spencer爱尔兰:英国马莎百货
2016/04/20 全球购物
Doyoueven官网:澳大利亚健身服饰和配饰品牌
2019/03/24 全球购物
班组长岗位职责范本
2014/01/05 职场文书
物业保安员岗位职责制度
2014/01/30 职场文书
公司会计岗位职责
2014/02/13 职场文书
员工辞退通知书
2015/04/17 职场文书
公司开除员工通知
2015/04/22 职场文书
浅谈Python魔法方法
2021/06/28 Java/Android