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

直入正题,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 = 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数组是按第一个参数倒序排列的

比如现在定义了

?

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))) {

    echo json_encode(array('code' => 500, 'msg' => '文件上传失败'));

  } else {

    echo json_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) {

    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>

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值