一个利用html5的图片裁剪功能(已解决ios压扁缩放等bug)

推荐:

这一篇文章是早年为了解决图片裁剪的探索性文章,现在已经开放出了falsh版及html5版本的图片裁剪插件,各位有时间可以看看:

浮士德html5图片裁剪器2016开源版

浮士德头像裁剪flash版2016福利版

上面两个解决方案已经经过几个项目,可以应用于低级浏览器及现代浏览器,ipad,移动设备等。



前言:

手机越来越普遍,利用手机即时拍照裁剪图片的功能需求是存在的。不才目前供职于一家网站,里面也有触屏版需要裁剪图片。



技术难点:

一般难点:

html5对图片的读取处理。

意外难点:

难点1、ios6,7下面对超过2M的图片有一个限制,该限制使得假如你直接将2m的本地图片或者相片绘制到canvas画布上面会出现压扁现象。

难点2、ios拍照会有额外的exif信息(图片信息),该信息包含了拍摄日期,作者,还有一个很关键的orientation(角度),ios拍摄有四个角度,分别为1,3,6,8,里面的代表含义记不清楚,不过就是表示,正拍,左旋90度,右旋90度,旋转180度。由于ios有这个orientation,所以假如用户使用ios的其他角度拍摄,直接绘制到画布上面会出现图片颠倒,并非用户希望的情形。这时候你就要根据角度进行调整了。


三、部分代码,为何这是部分代码?因为涉及到前端后端及样式,我没法提供完整代码,而且,涉及到公司机密,我只能提供一些我在解决bug途中所写的测试代码。

譬如,将图片颠倒缩小在放大,用于用户拖动裁剪框以后,js获得用户拖动的坐标,高度宽度,再根据相片的orientation逆推原本的坐标及正确的高度宽度,然后裁剪出那一部分图像,再根据orientation调整角度,必要时需要颠倒,缩放图像。

<html>
<head>
    <title>画布的旋转、缩放等功能。</title>
    <script type="text/javascript" src="/static/mobile/lib/zepto.min.js"></script>
</head>
<body>
<h1>选择:<a href="javascript:changeImg(6);">右旋90度图片</a> <a href="javascript:changeImg(3);">旋转180度图片</a> <a href="javascript:changeImg(8);">左旋90度图片</a> <a href="javascript:changeImg(1);">正常图片</a></h1>
<img id="sourceImg" src="images/exif_info_6.jpg" style="max-width: 400px;max-height: 400px;"/>
<fieldset>
    <legend>设置需要裁剪的x,y,及裁剪高度及宽度。</legend>
    <div>
        <table>
            <tr><td>x:</td><td><input type="text" id="txt_x" value="600"/></td></tr>
            <tr><td>y:</td><td><input type="text" id="txt_y" value="800"/></td></tr>
            <tr><td>width:</td><td><input type="text" id="txt_width" value="1480"/></td></tr>
            <tr><td>height:</td><td><input type="text" id="txt_height" value="850"/></td></tr>
            <tr><td>Orientation:</td><td><input type="text" id="txt_Orientation" value="6"/></td></tr>
            <tr><td>画布缩小倍数:</td><td><input type="text" id="txt_scale" value="5"/></td></tr>
            <tr><td> </td><td><input type="button" value="裁剪到临时画布" id="btn_saveToTmp"></td></tr>
        </table>
    </div>
    <div>临时画布:</div>
    <div style="border: 1px green solid;">
        <canvas id="canvas_tmp"></canvas>
    </div>
    <div>最终画布</div>
    <div style="border: 1px red solid;">
        <canvas id="canvas_final"></canvas>
        <div id="results"></div>
    </div>
</fieldset>


</body>
</html>
<script type="text/javascript">
    function changeImg(_Orientation){
        switch (_Orientation){
            case 8:
                setX(750);setY(220);setW(1800);setH(1200);setScale(5); setOrientation(8);
                _sourceImg.src="images/exif_info_8.jpg";
                break;
            case 6:
                setX(600);setY(800);setW(1480);setH(850);setScale(5); setOrientation(6);
                _sourceImg.src="images/exif_info_6.jpg";
                break;
            case 3:
                setX(600);setY(450);setW(2300);setH(1450);setScale(5);setOrientation(3);
                _sourceImg.src="images/exif_info_3.jpg";
                break;
            case 1:
                setX(600);setY(450);setW(2300);setH(1450);setScale(5);setOrientation(1);
                _sourceImg.src="images/exif_info_1.jpg";
                break;
        }
    }
    var _sourceImg=document.getElementById("sourceImg");
    var tmpCanvas=document.getElementById("canvas_tmp");
    var tmpContext=tmpCanvas.getContext("2d");
    var finalCanvas=document.getElementById("canvas_final");
    var finalContext=finalCanvas.getContext("2d");

    function getX(){
        return parseInt($("#txt_x").val());
    }
    function getY(){
        return parseInt($("#txt_y").val());
    }
    function getW(){
        return parseInt($("#txt_width").val());
    }
    function getH(){
        return parseInt($("#txt_height").val());
    }
    function getScale(){
        return parseFloat($("#txt_scale").val());
    }
    function getOrientatin(){
        return parseFloat($("#txt_Orientation").val());
    }
    function setX(x){
        $("#txt_x").val(x);
    }
    function setY(x){
        $("#txt_y").val(x);
    }
    function setW(x){
        $("#txt_width").val(x);
    }
    function setH(x){
        $("#txt_height").val(x);
    }
    function setScale(x){
        $("#txt_scale").val(x);
    }
    function setOrientation(x){
        $("#txt_Orientation").val(x);
    }
    function drawToTmpCanvas(x,y,w,h){
        tmpContext.clearRect(0,0,tmpCanvas.width,tmpCanvas.height) ;
        var _cW=parseFloat(w/getScale());
        var _cH=parseFloat(h/getScale());
        tmpCanvas.width=_cW;
        tmpCanvas.height=_cH;


        tmpContext.drawImage(_sourceImg,x,y,w,h,0,0,_cW,_cH);
    }


    $("#btn_saveToTmp").click(function(){
        drawToTmpCanvas(getX(),getY(),getW(),getH());
        var _cW=parseFloat(getW()/getScale());
        var _cH=parseFloat(getH()/getScale());
        $("#results").html("");
        var newCanvas=document.createElement("canvas");
        var newContext=newCanvas.getContext("2d");
        $("#results").append(newCanvas);
        drawToFinal(tmpCanvas,newCanvas,newContext,_cW,_cH,getOrientatin());
    });
    function drawToFinal(_sourceCanvas,_drawCanvas,_drawContext,_sw,_sh,_Orientation){

        switch(_Orientation){
            case 8:
                // 90 rotate left     --需要90度向左旋转。。那么,这个 PixelYDimension就是宽度了,PixelXDimension就是高度了。
                _drawCanvas.width=_sh;
                _drawCanvas.height=_sw;

                var tSetting={
                    dx:0,
                    dy:0,
                    dw:0,
                    dh:0,
                    transX:0,
                    transY:0
                };
                tSetting.dw=_sh;
                var scale2=_sw/_sh;
                tSetting.dh=parseFloat(tSetting.dw/scale2);
                tSetting.dy=(_sw-tSetting.dh)/2;
                tSetting.transY=_sw/2;
                tSetting.transX=_sh/2;
                _drawContext.translate(tSetting.transX,tSetting.transY);
                _drawContext.rotate(-0.5*Math.PI);
                _drawContext.scale(scale2,scale2);
                _drawContext.drawImage(_sourceCanvas,0,0,_sw,_sh,tSetting.dx-tSetting.transX,tSetting.dy-tSetting.transY,tSetting.dw,tSetting.dh);
                break;
            case 3:
                //180向左旋转 (右旋转也可以。)
                _drawCanvas.width=_sw;
                _drawCanvas.height=_sh;

                var tSetting={
                    dx:0,
                    dy:0,
                    dw:0,
                    dh:0,
                    transX:0,
                    transY:0
                };
                tSetting.dw=_sw;
                tSetting.dh=_sh;
                tSetting.transY=_sh/2;
                tSetting.transX=_sw/2;
                _drawContext.translate(tSetting.transX,tSetting.transY);
                _drawContext.rotate(1*Math.PI);
                //_drawContext.scale(scale2,scale2);
                _drawContext.drawImage(_sourceCanvas,0,0,_sw,_sh,tSetting.dx-tSetting.transX,tSetting.dy-tSetting.transY,tSetting.dw,tSetting.dh);
                break;
            case 6:
                //90 rotate right 需要向右旋转90度,PixelYDimension就是宽度了,PixelXDimension就是高度了。
                _drawCanvas.width=_sh;
                _drawCanvas.height=_sw;

                var tSetting={
                    dx:0,
                    dy:0,
                    dw:0,
                    dh:0,
                    transX:0,
                    transY:0
                };
                tSetting.dw=_sh;
                var scale2=_sw/_sh;
                tSetting.dh=parseFloat(tSetting.dw/scale2);
                tSetting.dy=(_sw-tSetting.dh)/2;
                tSetting.transY=_sw/2;
                tSetting.transX=_sh/2;
                _drawContext.translate(tSetting.transX,tSetting.transY);
                _drawContext.rotate(0.5*Math.PI);
                _drawContext.scale(scale2,scale2);
                _drawContext.drawImage(_sourceCanvas,0,0,_sw,_sh,tSetting.dx-tSetting.transX,tSetting.dy-tSetting.transY,tSetting.dw,tSetting.dh);
                break;
            case 1:
                //正常状态。
                _drawCanvas.width=_sw;
                _drawCanvas.height=_sh;

                var tSetting={
                    dx:0,
                    dy:0,
                    dw:0,
                    dh:0,
                    transX:0,
                    transY:0
                };
                tSetting.dw=_sw;
                tSetting.dh=_sh;
                tSetting.transY=_sh/2;
                tSetting.transX=_sw/2;
                _drawContext.translate(tSetting.transX,tSetting.transY);
               //_drawContext.rotate(1*Math.PI);
                //_drawContext.scale(scale2,scale2);
                _drawContext.drawImage(_sourceCanvas,0,0,_sw,_sh,tSetting.dx-tSetting.transX,tSetting.dy-tSetting.transY,tSetting.dw,tSetting.dh);
                break;
                break;
        }
    }

</script>


测试用结果如下:






而实际上线的效果如下:


打开图片裁剪页面:


点击头像,然后读取本地图片:


拖动裁剪框及下面的拖动条以调整裁剪框大小及位置,最后得到:



保存裁剪结果:


done。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值