直入正题,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