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

来源:互联网 发布:手机淘宝链接怎么弄 编辑:程序博客网 时间:2024/06/08 05:19

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

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

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

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

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

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

1. 打开摄像头

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

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

?
1
2
// 获取媒体方法(旧方法)
 navigator.getMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMeddia || navigator.msGetUserMedia;
?
1
2
3
4
5
6
7
8
9
10
11
12
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 对象下

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if(navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
    navigator.mediaDevices.getUserMedia({
      video:true,
      audio:true
    }).then(function(stream) {
      console.log(stream);
 
      mediaStreamTrack = typeofstream.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数组是按第一个参数倒序排列的

比如现在定义了

?
1
2
3
4
{
  video:true,
  audio:true
}

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

同理,0对应于audio的track

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

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

?
1
2
3
4
5
6
7
8
9
10
<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. 截取图像

将内容写入即可

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

3. 关闭摄像头

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

4. 上传截取的图像

canvas.toDataURL('image/png')

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 上传截取的图像
  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的头部信息字段去掉再保存,否则似乎图像是损坏无法打开滴

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?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))) {
    echojson_encode(array('code'=> 500, 'msg'=> '文件上传失败'));
  }else{
    echojson_encode(array('code'=> 200, 'msg'=> '文件上传成功','path'=> $uploadDir. $fileName));
  }
 
?>

完整JS代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
<script type="text/javascript"src="jquery.js"></script>
  <script type="text/javascript">
  function$(elem) {
    returndocument.querySelector(elem);
  }
 
  // 获取媒体方法(旧方法)
  navigator.getMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMeddia || navigator.msGetUserMedia;
 
  varcanvas = $('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 = typeofstream.stop === 'function'? stream : stream.getTracks()[1];
 
      video.src = (window.URL || window.webkitURL).createObjectURL(stream);
      video.play();
    }).catch(function(err) {
      console.log(err);
    })
  }
  // 使用旧方法打开摄像头
  elseif (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>

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

原文链接:http://www.cnblogs.com/imwtr/p/6413595.html

原创粉丝点击