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 相关文章推荐
jquery $.ajax相关用法分享
Mar 16 Javascript
网页源代码保护(禁止右键、复制、另存为、查看源文件)
May 23 Javascript
深入浅出分析javaScript中this用法
May 09 Javascript
js实现跨域的4种实用方法原理分析
Oct 29 Javascript
JQuery日期插件datepicker的使用方法
Mar 03 Javascript
jQuery中通过ajax调用webservice传递数组参数的问题实例详解
May 20 Javascript
总结JavaScript的正则与其他语言的不同之处
Aug 25 Javascript
微信小程序 获取设备信息 API实例详解
Oct 02 Javascript
详解.vue文件中style标签的几个标识符
Jul 17 Javascript
koa router 多文件引入的方法示例
May 22 Javascript
iview的table组件自带的过滤器实现
Jul 12 Javascript
在vue中获取wangeditor的html和text的操作
Oct 23 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
聊天室php&amp;mysql(六)
2006/10/09 PHP
php截取字符串之截取utf8或gbk编码的中英文字符串示例
2014/03/12 PHP
thinkphp中memcache的用法实例
2014/11/29 PHP
php中使用key,value,current,next和prev函数遍历数组的方法
2015/03/17 PHP
php支持断点续传、分块下载的类
2016/05/02 PHP
PHP分享图片的生成方法
2018/04/25 PHP
PHP与Perl之间知识点区别整理
2019/03/19 PHP
JavaScript 获取事件对象的注意点
2009/07/29 Javascript
你必须知道的Javascript知识点之&quot;单线程事件驱动&quot;的使用
2013/04/23 Javascript
微信小程序-图片、录音、音频播放、音乐播放、视频、文件代码实例
2016/11/22 Javascript
Bootstrap源码解读导航(6)
2016/12/23 Javascript
AngularJS1.X学习笔记2-数据绑定详解
2017/04/01 Javascript
详解angular ui-grid之过滤器设置
2017/06/07 Javascript
js 概率计算(简单版)
2017/09/12 Javascript
js中let和var定义变量的区别
2018/02/08 Javascript
webpack实现一个行内样式px转vw的loader示例
2018/09/13 Javascript
js刷新页面location.reload()用法详解
2019/12/09 Javascript
使用Typescript开发微信小程序的步骤详解
2021/01/12 Javascript
python 算法 排序实现快速排序
2012/06/05 Python
Python中import机制详解
2017/11/14 Python
Python使用py2neo操作图数据库neo4j的方法详解
2020/01/13 Python
Python面向对象编程基础实例分析
2020/01/17 Python
python实现全排列代码(回溯、深度优先搜索)
2020/02/26 Python
PyCharm MySQL可视化Database配置过程图解
2020/06/09 Python
MAC平台基于Python Appium环境搭建过程图解
2020/08/13 Python
PyCharm设置注释字体颜色以及是否倾斜的操作
2020/09/16 Python
香港时装购物网站:ZALORA香港
2017/04/23 全球购物
网络体系结构及协议的定义
2014/03/13 面试题
物业管理员岗位职责范文
2013/11/25 职场文书
护士见习期自我鉴定
2014/02/08 职场文书
2014年两会学习心得体会
2014/03/17 职场文书
群众路线教育实践活动个人对照检查材料思想汇报(社区班子)
2014/10/06 职场文书
2015商场元旦促销活动策划方案
2014/12/09 职场文书
2019个人工作自我评价范文(3篇)
2019/09/19 职场文书
MySql 缓存查询原理与缓存监控和索引监控介绍
2021/07/02 MySQL
Python Matplotlib绘制条形图的全过程
2021/10/24 Python