HTML5 PC、Mobile调用摄像头(navigator.getUserMedia)

废话少说,先贴上代码

html:

 1 <div id="main" class="masthead">
 2     <div id="face_scan_camera" class="container blackbg" style="height:792px; ">
 3         <div style="width:1400px;margin:0 auto;">
 4             <video id="video" width="1400" height="790" autoplay="autoplay" style="margin:0 auto;position:relative;z-index:100;"></video>                
 5         </div>
 6         <div class="camera-mask"></div>
 7         <div class="camera-area" style="width:450px;height:350px;background:url(/images/lifescan/scan_kuang1.png) no-repeat;z-index:102;top:560px;left:780px;"> 
 8             <img src="/images/lifescan/scan_kuang1.png" />
 9             <div class="scan-area" style="height:585px;width:580px;display:none; ">
10                 <canvas id="canvas" width="1054" height="790" style="display:inline-block; margin:0 auto;position:relative;left:13px;top:70px;z-index:100;"></canvas>                    
11             </div>
12             <a id="snap" ><img src="/images/lifescan/camera_btn.png" /></a>
13         </div>
14     </div>
15     <div id="cream_loading" style="display:none;position:absolute; margin:-62px 0 0 -62px;top:50%;left:50%;height:124px;width:124px;z-index:2001;"><img  src="/Images/cream_loading.gif"/></div>       
16 </div>
View Code
var scan_param = {};
var scanInterval;
var sn = 0;
var sel, fr;
$(function () {
    $('#canvas').hide();
    try {
        sel = document.getElementById('fileselect'); // get reference to file select input element

        window.addEventListener("DOMContentLoaded", function () {
            // Grab elements, create settings, etc.
            var canvas = document.getElementById("canvas"),
            context = canvas.getContext("2d"),
            video = document.getElementById("video"),
            videoObj = { "video": true },
            errBack = function (error) {
                if (error.PERMISSION_DENIED) {
                    //swal("", privacyRequiredMsg, "warning");
                    swal("",'用户拒绝了浏览器请求媒体的权限', 'warning');
                } else if (error.NOT_SUPPORTED_ERROR) {
                    swal("", '对不起,您的浏览器不支持拍照功能,请使用其他浏览器', 'warning');
                } else if (error.MANDATORY_UNSATISFIED_ERROR) {
                    swal("", '指定的媒体类型未接收到媒体流', 'warning');
                } else {
                    swal("", '系统未能获取到摄像头,请确保摄像头已正确安装。或尝试刷新页面,重试', 'warning');
                }
            };

            var message = "为了获得更准确的测试结果,请尽量将面部置于红框中,然后进行拍摄、扫描。 点击“OK”后,请在屏幕上方出现的提示框选择“允许”,以开启摄像功能";
            // Put video listeners into place
            if (navigator.getUserMedia) { // Standard
                if (navigator.userAgent.indexOf('MQQBrowser') > -1) {
                    swal("",'对不起,您的浏览器不支持拍照功能,请使用其他浏览器', 'warning');
                    return false;
                }
                swal({
                    title: "",
                    text: message,
                    type: "warning",
                    showCancelButton: false,
                    confirmButtonColor: "#DD6B55",
                    confirmButtonText: "OK",
                    closeOnConfirm: true
                },
                function (isConfirm) {
                    $(document).scrollTop($(window).height());
                });
                navigator.getUserMedia(videoObj, function (stream) {
                    video.src = stream;
                    video.play();
                    $('#lifescan #main .btn_click').css('margin-top', '-550px');
                    video.addEventListener('loadeddata', function () {
                        $(document).scrollTop($(window).height());
                    }, false);
                    $('#snap').click(function () {
                        //$('.scan-area').show();
                        $('#cream_loading').toggle();
                        context.drawImage(video, 0, 0, 640, 480);
                        convertCanvasToImage();
                    });
                }, errBack);
            } else if (navigator.webkitGetUserMedia) { // WebKit-prefixed
                swal({
                    title: "",
                    text: message,
                    type: "warning",
                    showCancelButton: false,
                    confirmButtonColor: "#DD6B55",
                    confirmButtonText: "OK",
                    closeOnConfirm: true
                },
                function (isConfirm) {
                    $(document).scrollTop($(window).height());
                });
                navigator.webkitGetUserMedia(videoObj, function (stream) {
                    video.src = window.webkitURL.createObjectURL(stream);
                    video.play();
                    $('#lifescan #main .btn_click').css('margin-top', '-550px');
                    video.addEventListener('loadeddata', function () {
                        $(document).scrollTop($(window).height());
                    }, false);
                    if (navigator.userAgent.indexOf('UCBrowser') > -1) {
                        $('#lifescan #main .btn_click').css('margin-top', '-10px');
                    }
                    $('#snap').click(function () {
                        $('#cream_loading').toggle();
                        context.drawImage(video, 0, 0, 640, 480);
                        convertCanvasToImage();
                    });
                }, errBack);

            }
            else if (navigator.mozGetUserMedia) { // Firefox-prefixed
                swal({
                    title: "",
                    text: message,
                    type: "warning",
                    showCancelButton: false,
                    confirmButtonColor: "#DD6B55",
                    confirmButtonText: "OK",
                    closeOnConfirm: true
                },
                function (isConfirm) {
                    $(document).scrollTop($(window).height());
                });
                navigator.mozGetUserMedia(videoObj, function (stream) {
                    video.src = window.URL.createObjectURL(stream);
                    video.play();
                    video.addEventListener('loadeddata', function () {
                        $(document).scrollTop($(window).height());
                    }, false);
                    $('#lifescan #main .btn_click').css('margin-top', '-550px');

                    $('#snap').click(function () {
                        $('#cream_loading').toggle();
                        context.drawImage(video, 0, 0, 640, 480);
                        convertCanvasToImage();
                    });
                }, errBack);

            }
            else if (navigator.msGetUserMedia) {
                swal({
                    title: "",
                    text: message,
                    type: "warning",
                    showCancelButton: false,
                    confirmButtonColor: "#DD6B55",
                    confirmButtonText: "OK",
                    closeOnConfirm: true
                },
                function (isConfirm) {
                    $(document).scrollTop($(window).height());
                });
                navigator.msGetUserMedia(videoObj, function (stream) {
                    $(document).scrollTop($(window).height());
                    video.src = window.URL.createObjectURL(stream);
                    video.play();
                    $('#lifescan #main .btn_click').css('margin-top', '-550px');
                    video.addEventListener('loadeddata', function () {
                        $(document).scrollTop($(window).height());
                    }, false);
                    $('#snap').click(function () {
                        $('#cream_loading').toggle();
                        context.drawImage(video, 0, 0, 640, 480);
                        convertCanvasToImage();
                    });
                }, errBack);

            }
            else {
                var userAgent = navigator.userAgent;
                if (navigator.vendor == "Apple Computer, Inc.") {//这里是对Safari浏览器的判断
                    sel.addEventListener('change', function (e) {
                        var f = sel.files[0]; // get selected file (camera capture)
                        fr = new FileReader();
                        fr.onload = receivedData; // add onload event

                        fr.readAsDataURL(f); // get captured image as data URI
                    });
                    $('#imgtag').show();
                    //$('.div_video').hide();
                    $('#snap').click(function () {
                        sel.click();
                    });
                } //判断是否Safari浏览器
                else {
                    swal("", "对不起,您的浏览器不支持拍照功能,请使用其他浏览器", "warning");
                }
            }
        }, false);
    }
    catch (err) {
        swal("", "对不起,您的浏览器不支持拍照功能,请使用其他浏览器", "warning");
    }
});
// for iOS 
// create file reader
function receivedData() {
    // readAsDataURL is finished - add URI to IMG tag src
    $('.div_video #video').hide();
    $('.div_video #imgtag').show();
    var canvas = document.getElementById("canvas");
    var context = canvas.getContext("2d");
    var imgtag = document.getElementById('imgtag'); // get reference to img tag
    imgtag.src = fr.result;
    $('#cream_loading').toggle();

    try {
        setTimeout(function () {
            context.drawImage(imgtag, 0, 0, 640, 480);
            convertCanvasToImage();
        }, 500);

    }
    catch (err) {
        swal(err, "warning");
    }
}
//帆布转换成图像并保存图片
function convertCanvasToImage(canvas) {
    var image = new Image();
    image.src = document.getElementById("canvas").toDataURL("image/png");
    //alert(image.src);
    //删除字符串前的提示信息“data:image/png;base64”
    var b64 = image.src.substring(22);
    var myDate = new Date();
    var filename = myDate.getTime();
    $.post("/Article/SavePhoto", { data: b64, name: filename }, function (result) {
        if (result.success) {
            $('#cream_loading').toggle();
            window.location.href = "/yourreenex?photo=" + result.photo;
        }
    });
    return image;
}

function initScanParam() {
    scan_param = {
        lineHeight: 0
    };
    scan_param.scanBorder = $('.scan-area').height();
    var $scan = $('.scanL');
    scan_param.scanTop = $scan.css('top');
    scan_param.scanHeight = $scan.css('height');
}
function scanImage() {
    var $scan = $('.scanL');

    var top = Math.ceil(parseFloat($scan.css('top')));
    //alert(top +"||"+ scan_param.lineHeight +"|||"+ scan_param.scanBorder);
    if (top < scan_param.scanBorder) {
        //alert(top + "||" + scan_param.lineHeight + "|||" + scan_param.scanBorder);
        $scan.css({ 'top': (top + 1) + 'px', 'height': ($scan.height() - 1) + 'px' });
        if ($scan.height() == 0) {
            $('.right .result-number').text(createData(40, 100) + "%");
        }
    } else {

        clearInterval(scanInterval);
    }
}


//分析浏览器是否支持
function isStreamSupported() {
    if (navigator.mozGetUserMedia) {
        return true;
    }
    else {
        return false;
    }
}
navigator.vendor == "Apple Computer, Inc." 这句的解释请看这篇文章http://www.cnblogs.com/lechenging/p/4226494.html 

 然后说一下这个兼容性,目前支持,PC端:chrome,Firefox,360;移动端:chrome,Firefox,UC,Safair(这个的调用跟其他有点区别,后面会说道)

接着上图片:PC端的没上图片,第一张是mobile chrome,后面两张是mobile firefox

 
 
 然后我们来说一下代码,html代码中其中用到的就是video 跟canvas  标签,其中canvas是隐藏的,其中的height width 不是卸载style那种。
 
我们还是来重点说明一下js代码吧
 
为了兼容不同的浏览器我们这里对navigator.getUserMedia 进行了判断,因为手机上video的width实在不好控制要满屏,所以我特意放大了,但这样就会有一个拍照按钮被撑到了下面,需要滑动页面才能找到,用户体验不好,为了解决这一问题我给video  添加了 'loadeddata'事件,让页面能再及时的自动下滑到地步
 
再来说一下拍照,用到了context.drawImage(video, 0, 0, 640, 480);但这样并不能达到生成图片的目的,所以后面我又用到了convertCanvasToImage()函数
 
 
我再来说一下对Safair的处理,safair似乎不支持navigator.getUserMedia,再一大牛的帮助下,处理找到了另一种处理方法:
 
就是调用safair自己的拍照来实现,sel.addEventListener('change', function (e){...}) 就是添加了 你选取的是拍照还是图片的事件,后面的receivedData()函数是对其的处理,其中的一定要做一个setTimeout,苹果的图片高质量,加载没有那么迅速,为了让drawImage能够取到已经加载的图片要做一个延时,否则会取不到图片
 
 
为了解决程序处理图片速度慢的问题,我还加了一个loading图片,来提高用户体验。
 
对了忘了说一下,safair拍出的图片是反着的,我也不知道怎么回事,大家有知道,希望指点一下!!!
 
 
 
 
 
posted @ 2014-09-26 23:15  lechenging  阅读(7602)  评论(8编辑  收藏  举报