• html5调用手机相机并压缩、上传


    近日刚做的一个功能,要在app里使用内嵌页面进行图像的上传。
    从功能上看,原生的实现应该是最好的。毕竟页面上所有的东西都隔着一个浏览器,所有的实现都要依赖浏览器提供的接口,不同的浏览器对接口的实现又有差异……到最后又会陷入兼容性的大坑!
    吐槽归吐槽,但是折腾的劲头不能丢!

    使用input file[camera]属性调用相机

    简直So easy!

    <input type="file" accept="image/*;" capture="camera" >
    

    只需要这么一条简单的代码,在手机浏览器点击就可以打开相机了。

    capture是什么?其实就是对打开方式的设置。

    <!-- capture=camcorder,调用手机摄像功能 -->
    <input type="file" accept="video/*" capture="camcorder" > 
    <!-- capture=microphone,调用手机录音功能 -->
    <input type="file" accept="audio/*" capture="microphone" >
    

    魅族MX5测试结果:

    • 谷歌浏览器可以打开相机和摄像功能,其他方式均为相机、图库、文件管理器等混合选择项。
    • 自带浏览器打开均为文件管理器。

    由此说明此属性兼容性还是个问题。不过这并不能阻止我继续折腾下去!

    图片压缩

    在如今这个手机普遍千万像素的时代,一张照片动辄5M的大小。作为一个良心的开发者,我们是要为用户的流量负责的。
    该怎么做?我也不知道。大家都在用canvas实现,我也就用了。

    document.getElementById('file').addEventListener('change', function() {
    
        var reader = new FileReader();
    
        reader.onload = function (e) {
            compress(this.result);
        };
    
        reader.readAsDataURL(this.files[0]);
    
    }, false);
    

    不管文件域是用何种方式打开的,都可以在 change 事件中获取到选择的文件或拍摄的照片。

    创建一个FileReader对象,我们需要调用readAsDataURL把文件转换为base64图像编码,如data:image/jpeg;base64……这种格式。
    onload是一个异步回调,当文件读取完执行该方法内代码。this.result记录读取结果,如果读取失败,该值为null。在这里进行图片压缩的具体操作。

    var compress = function (res) {
        var img = new Image(),
            maxH = 160;
    
        img.onload = function () {
            var cvs = document.createElement('canvas'),
                ctx = cvs.getContext('2d');
    
            if(img.height > maxH) {
                img.width *= maxH / img.height;
                img.height = maxH;
            }
    
            cvs.width = img.width;
            cvs.height = img.height;
    
            ctx.clearRect(0, 0, cvs.width, cvs.height);
            ctx.drawImage(img, 0, 0, img.width, img.height);
    
            var dataUrl = cvs.toDataURL('image/jpeg', 0.6);
    
            // 上传略
        }
    
        img.src = res;
    }
    

    创建一个Image对象,给src属性赋值为读取结果,同样在onload异步回调中编写处理图片的代码。
    这里就要开始使用canvas进行图片压缩了。

    首先是尺寸按比例缩放,然后把图片绘到画布上,最后调用toDataURL方法压缩图像质量。

    context.toDataURL('MIME类型', 图像质量0-1);  // 该方法返回base64图像编码
    

    代码里省略了一些校监操作,如文件类型约束和文件大小判断(小于一定值可以不压缩)。
    最后就是把数据发送到后端的操作,这里就不说了。

    Html5调用摄像头

    通过以上的代码已经可以实现调用手机相机拍照、压缩、上传这一整套流程了。
    不过在折腾的过程中也发现了一种调用摄像头的方法。注意,是摄像头!使用input调用的是相机。其中的差别就是摄像头是只捕获画面,相机还包括原生的一些拍照、设置等控件。

    通过对摄像头的调用可以做很多有趣的事,比如拍照美化、滤镜等。可以说实现一个第三方相机是没问题的。
    之前下载过一款安卓相机APP,不到100K的大小,可以实现拍照的一些风格化,也许就是Html5实现的呢。

    需要用到的是 getUserMedia API,具体的实现这里就不贴了。

    【用到的HTML5标签】

    1
    <input type="file" capture="camera" accept="image/*" id="cameraInput" name="cameraInput" class="sign_file"/>

    【等比缩放图片】

    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
    function drawOnCanvas(file) {
        var reader = new FileReader();
        reader.onload = function(e) {
            var dataURL = e.target.result,
            canvas = document.querySelector('canvas'),
            ctx = canvas.getContext('2d'),
            img = new Image();
            img.onload = function() {
                var square = 320;
                canvas.width = square;
                canvas.height = square;
                var context = canvas.getContext('2d');
                context.clearRect(0, 0, square, square);
                var imageWidth;
                var imageHeight;
                var offsetX = 0;
                var offsetY = 0;
                if (this.width > this.height) {
                    imageWidth = Math.round(square * this.width / this.height);
                    imageHeight = square;
                    offsetX = -Math.round((imageWidth - square) / 2);
                } else {
                    imageHeight = Math.round(square * this.height / this.width);
                    imageWidth = square;
                    offsetY = -Math.round((imageHeight - square) / 2);
                }
                context.drawImage(this, offsetX, offsetY, imageWidth, imageHeight);
                var base64 = canvas.toDataURL('image/jpeg', 0.5);
                $('#j_thumb').val(base64.substr(22));
            };
            img.src = dataURL;
        };
        reader.readAsDataURL(file);
    }

    FileReader对象是用来解析file控件获取的本地图片地址的,具体介绍请百度一下。把解析好的地址设置给IMG标签的SRC属性,然后通过canvas对象把图片绘制; 在这过程中就有个等比缩放的算法,再用drawImage方法把图像画到canvas中。
    【如何获取画好的图片数据传到后端处理】
    通过 canvas.toDataURL(‘image/jpeg’,0.5)就可以获取到base64编码值,然后你就可以按照传统的POST或者AJAX方式处理了。

    【让图片显示】

    1
    2
    3
    4
    document.querySelector('input[type=file]').onchange = function() {
        var file = input.files[0];
        drawOnCanvas(file);
    };

    【后台处理方式】

    1
    2
    3
    $base64 = $_POST['formFile'];
    $IMG = base64_decode( $base64 );
    file_put_contents('1.png', $IMG );

    根传统的上传图片不同,这时候后台需要用base64_decode解码

     DEMO下载地址

  • 相关阅读:
    [转]说说JSON和JSONP,也许你会豁然开朗,含jQuery用例
    [转]Vue-Devtools安装配置教程(献给伸手党)
    [转]vscode 插件推荐
    [转]eclipse中explorer显示方式
    [转]小D课堂
    [转]eclipse中 properties文件编码问题
    [转]windows环境下启动与停止.jar文件
    [转]Maven 国内源配置(2019/2/14)
    [转]Maven 全局配置文件settings.xml详解
    [转]IntelliJ IDEA 2019 上手
  • 原文地址:https://www.cnblogs.com/sunshq/p/5082272.html
Copyright © 2020-2023  润新知