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 相关文章推荐
JavaScript中令你抓狂的魔术变量
Nov 30 Javascript
Jquery 过滤器(first,last,not,even,odd)的使用
Jan 22 Javascript
JS使用ajax方法获取指定url的head信息中指定字段值的方法
Mar 24 Javascript
jQuery无刷新切换主题皮肤实例讲解
Oct 21 Javascript
javascript发送短信验证码实现代码
Nov 12 Javascript
Bootstrap table表格简单操作
Feb 07 Javascript
ionic实现底部分享功能
May 11 Javascript
详解vue文件中使用echarts.js的两种方式
Oct 18 Javascript
解决JavaScript中0.1+0.2不等于0.3问题
Oct 23 Javascript
vue里如何主动销毁keep-alive缓存的组件
Mar 21 Javascript
uni-app如何实现增量更新功能
Jan 03 Javascript
jQuery操作元素的内容和样式完整实例分析
Jan 10 jQuery
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中转义mysql语句的实现代码
2011/06/24 PHP
PHP中call_user_func_array()函数的用法演示
2012/02/05 PHP
PHP不用递归实现无限分级的例子分享
2014/04/18 PHP
php include类文件超时问题处理
2015/02/06 PHP
php示例详解Constructor Prototype Pattern 原型模式
2015/10/15 PHP
php file_get_contents取文件中数组元素的方法
2017/04/01 PHP
PHP实现的常规正则验证helper公共类完整实例
2017/04/27 PHP
Laravel5.5 数据库迁移:创建表与修改表示例
2019/10/23 PHP
js拖动div 当鼠标移动时整个div也相应的移动
2013/11/21 Javascript
Nodejs异步回调的优雅处理方法
2014/09/25 NodeJs
JsRender for index循环索引用法详解
2014/10/31 Javascript
javascript实现检验的各种规则
2015/07/31 Javascript
Javascript的无new构建实例详解
2016/05/15 Javascript
jQuery异步提交表单的两种方式
2016/09/13 Javascript
简单实现IONIC购物车功能
2017/01/10 Javascript
docker中编译nodejs并使用nginx启动
2017/06/23 NodeJs
Angularjs单选框相关的示例代码
2017/08/17 Javascript
获取本机IP地址的实例(JavaScript / Node.js)
2017/11/24 Javascript
js实现点击上传图片并设为模糊背景
2020/08/02 Javascript
原生js拖拽功能制作滑动条实例代码
2021/02/05 Javascript
python实现linux服务器批量修改密码并生成execl
2014/04/22 Python
Python比较文件夹比另一同名文件夹多出的文件并复制出来的方法
2015/03/05 Python
Python装饰器实现几类验证功能做法实例
2017/05/18 Python
Python机器学习之决策树算法实例详解
2017/12/06 Python
python关于变量名的基础知识点
2020/03/03 Python
django下创建多个app并设置urls方法
2020/08/02 Python
Django+Django-Celery+Celery的整合实战
2021/01/20 Python
原生canvas制作画图小工具的踩坑和爬坑
2020/06/09 HTML / CSS
美国在线自行车商店:Jenson USA
2018/05/22 全球购物
您附近的水疗和健康场所:Spafinder(美国)
2019/07/05 全球购物
应届生求职简历的自我评价怎么写
2013/10/23 职场文书
爱岗敬业演讲稿范文
2014/01/14 职场文书
小学远程教育工作总结
2015/08/13 职场文书
Ajax是什么?Ajax高级用法之Axios技术
2021/04/21 Javascript
修改MySQL的数据库引擎为INNODB的方法
2021/05/26 MySQL
python前后端自定义分页器
2022/04/13 Python