使用HTML5 canvas 標籤進行圖片裁剪、旋轉、縮放

代碼使用到的js插件:jquery、bootstrap、lrz。
jquery就不說了,基本都知道。bootstrap是一個響應式的前端ui框架。使用它是爲了在手機端查看頁面時能夠自適應寬高。lrz是一個前端的js壓縮圖片的插件。
效果圖:
這裏寫圖片描述
截圖後的圖片:
這裏寫圖片描述

源代碼下載:點擊下載
HTML頁面代碼:

<html lang="zh-CN">
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">    

    <title>圖片裁剪</title>

    <link href="css/bootstrap.min.css" rel="stylesheet">
    <link href="css/imgUpload.css" rel="stylesheet">
</head> 

<body class="container" style="background-color: #C0C0C0;">
    <div class="row-fluid">
        <input type="file" class="btn btn-default" /> 
        <div class="row-fluid col-sm-12 col-md-12 item" id="canvasDivId">
            <canvas id="myCanvas" width="400" height="550" class="img-responsive"
                style="border:1px solid #d3d3d3;display:none;">
            你的瀏覽器不支持HTML5. </canvas>  
        </div> 
        <div class="row-fluid col-sm-12 col-md-12">
            <canvas id="myCanvasTow" width="320" height="400" class="img-responsive"
                style="border:1px solid #d3d3d3;display:none;">
            你的瀏覽器不支持HTML5. </canvas>
        </div>
        <div class="row-fluid col-sm-12 col-md-12" id="anniuDiv"
            style="display:none;">
                <button type="button" class="btn btn-success" id="affirmId">確認</button>
                <!--<img alt="逆時針旋轉" title="逆時針旋轉" style="width: 30px;height: 30px;" id="rotateLeft" src="imageUpload/left.png">-->
                <img alt="順時針旋轉" title="順時針旋轉" style="width: 30px;height: 30px;" id="rotateRight" src="imageUpload/right.png">
                <img alt="縮小" title="縮小" style="width: 30px;height: 30px;" id="scale" src="imageUpload/rrrr.png">
                <img alt="放大" title="放大" style="width: 30px;height: 30px;" id="little" src="imageUpload/pppp.png">
                <button type="button" class="btn btn-primary" id="buttonId">預覽</button>
                <button type="button" class="btn btn-danger" style="display: none;" id="resetId">重置</button>
        </div>     
        <div class="row-fluid col-sm-12 col-md-12"> 
            <img id="cutImgId" class="img-responsive" src=""
                style="width: 320;height: 400;display:none;">
        </div>
    </div>
    <script type="text/javascript" src="js/jquery-1.11.1.js"></script>
    <script src="js/bootstrap.min.js"></script>
    <script type="text/javascript" src="js/img2.js"></script>
    <script type="text/javascript" src="js/lrz.pc.min.js"></script>
    <script type="text/javascript" src="js/lrz.mobile.min.js"></script>
    <script type="text/javascript"> 
        var ics = new imgStroke();
        $('input[type=file]').change(function(){
            var file=this.files[0];
            var reader=new FileReader();
            reader.οnlοad=function(){ 
                // 通過 reader.result 來訪問生成的 DataURL
                var url=reader.result;
                ics.init({"canvasId":"myCanvas","url":url,"x":20,"y":20});
                demo_report();
            };       
            reader.readAsDataURL(file);
        });
    </script>
</body>
</html>

img2.js的js代碼:

var tempContext = null,     //全局Context對象
canvas = null,              /**畫布**/
imageObj = null,            //全局圖片對象
imageRotate = null,         //旋轉後的圖片
oX=null,                    //矩形框X座標
oY=null,                    //矩形框Y座標
started=false,              //標識鼠標移動時是否重繪
n = 0,                      //旋轉步驟
width = 0,                  //矩形裁剪框寬度 
height = 0,                 //矩形裁剪框高度
imgW = 400,                 //圖片的寬
imgH = 550,                 //圖片的高 
canvasW = 400,              //畫布的寬
canvasH = 550,              //畫布的高 
moveSwitch = false;         //全局開關
var imgStroke = (function(){
    //構造函數   
    function ics(){
        canvas = null; 
        oX = 20; /**加載時矩形左上角的 x 座標**/
        oY = 20; /**加載時矩形左上角的 y 座標**/
        width = 320; /**加載時初始化矩形框的寬**/
        height = 400; /**加載時初始化矩形框的高**/
        imageRotate = null;
        moveSwitch = true;
    }  
    /** 
     * 初始化
     */
    ics.prototype.init = function(obj){
        /**如果畫布有內容則清除**/ 
        if(tempContext){
            clearCanvas();
        } 
        canvas = document.getElementById(obj.canvasId); /**畫布**/
        canvas.width = canvasW;
        canvas.height = canvasH; 
        tempContext = canvas.getContext("2d"); 
        var imageUrl = new Image();
        imageUrl.src = obj.url; 
        imageObj = imageUrl; /**圖片**/
        if(obj.x)
            oX = obj.x; /**矩形左上角的 x 座標**/
        if(obj.y)
            oY = obj.y; /**矩形左上角的 y 座標**/
        if(obj.width) 
            width = obj.width; 
        if(obj.height) 
            height = obj.height; 
        $("#"+obj.canvasId).show();
        /**加載圖片並繪製矩形框**/ 
        loadImgRect(oX,oY,"load"); 
        // 鼠標事件 
        canvas.addEventListener("mousedown", doMouseDown, false);  
        canvas.addEventListener('mousemove', doMouseMove, false);  
        canvas.addEventListener('mouseup',   doMouseUp, false); 
        // 觸屏事件
        canvas.addEventListener("touchstart",doMouseDown,false);  
        canvas.addEventListener("touchmove",doMouseMove,false);  
        canvas.addEventListener("touchend",doMouseUp,false); 
    }
    /**
     * 加載圖片並繪製矩形框 
     */
    function loadImgRect(x,y,type){ 
        if(!moveSwitch){
            return;
        }
        /**
         * 判斷移動是否超出畫布
         * 畫布的寬度減去裁剪框的寬度得到x座標在畫布中的最大值
         * 畫布的高度減去裁剪框的高度得到y座標在畫布中的最大值 
         */
        if(x>(canvasW-width)){ x= (canvasW-width); }
        if(y>(canvasH-height)){ y= (canvasH-height); } 
        if(x<0)x=0;if(y<0)y=0;

        if((!type||type!="load")&&imageRotate){ 
              imageObj = imageRotate;
        }     
        oX = x; oY = y; 
        clearCanvas();    
        /**從新設置透明度爲1**/
        tempContext.globalAlpha = 1; 
        tempContext.drawImage(imageObj, 0, 0, imgW, imgH);
        tempContext.globalAlpha=0.7;   
        tempContext.fillStyle='#F8F8F8';  
        tempContext.fillRect(x,y,width,height);   
    }            
    /**
     * 座標換算
     * 相對頁面來講:上下爲y軸 左右爲x軸
     * 用當前頁面的x座標減去畫布與頁面左邊的距離從而得到當前鼠標在畫布中的x座標 
     * 用當前頁面的y座標減去畫布與頁面頭部的距離從而得到當前鼠標在畫布中的y座標 
     * 乘以(canvas.width  / bbox.width)跟(canvas.height / bbox.height)是爲了綜合畫布實際大小而做的一個誤差填補計算。畫寬高的誤差值在2px左右
     */ 
    function getPointOnCanvas(canvas, x, y) {   
        var bbox = canvas.getBoundingClientRect(); 
        return { x: x - bbox.left * (canvas.width  / bbox.width),  
                y: y - bbox.top  * (canvas.height / bbox.height) };  
    }     
    /**
     * 清除畫布
     */  
    function clearCanvas() {
        tempContext.clearRect(0, 0, canvasW,canvasH);  
    }          

    /**
     * 鼠標按下事件
     */
    function doMouseDown(event) {  
        event.preventDefault();  
        event.stopPropagation(); 
        var x = null,y = null;
        /**獲取鼠標相對於文檔(頁面)的位置**/ 
        if(event.changedTouches){
            x=event.changedTouches[0].pageX;  
            y=event.changedTouches[0].pageY;  
        }else{
            x=event.pageX;    
            y=event.pageY;    
        }  
        var canvas = event.target;  
        var loc = getPointOnCanvas(canvas, x, y);  
        /**加載圖片並繪製矩形框**/
        loadImgRect(loc.x, loc.y);
        started = true;  
    }  
    /**   
     * 鼠標移動事件
     */
    function doMouseMove(event) {  
        event.preventDefault();  
        event.stopPropagation();
        var x = null,y = null;
        /**獲取鼠標相對於文檔(頁面)的位置**/
        if(event.changedTouches){
            x=event.changedTouches[0].pageX;  
            y=event.changedTouches[0].pageY;  
        }else{
            x=event.pageX;     
            y=event.pageY;    
        }
        var canvas = event.target;  
        var loc = getPointOnCanvas(canvas, x, y);  
        if (started) {    
            /**加載圖片並繪製矩形框**/ 
            loadImgRect(loc.x, loc.y);
        }  
    }  
    /**
     * 鼠標按起事件
     */
    function doMouseUp(event) {  
        event.preventDefault();  
        event.stopPropagation(); 
        if (started) {  
            doMouseMove(event);   
            started = false;  
        }   
    } 

    /**確認裁剪**/
    ics.prototype.getImageData=function(id){
        if(!moveSwitch){
            return; 
        }
        if(imageRotate){
              imageObj = imageRotate;
        }    
        /**去掉裁剪框填充背景色**/
        clearCanvas();  
        /**恢復默認透明度爲不透明**/
        tempContext.globalAlpha = 1; 
        tempContext.drawImage(imageObj, 0, 0, imgW, imgH);
        tempContext.strokeStyle="#FFFFFF";
        tempContext.strokeRect(oX,oY,width,height); 
        /**獲取數據**/        
        var data = tempContext.getImageData(oX,oY,width,height);
        var canvasTow = document.getElementById("myCanvasTow");
        var ctxTow = canvasTow.getContext("2d");  
        ctxTow.putImageData(data,0,0);   
        var imgData = canvasTow.toDataURL();
        loadImgRect(oX,oY);       
        lrz(imgData, {     
            width:width, 
            height:height,    
            // 壓縮開始 
            before: function() {
                console.log('壓縮開始');
            },
            // 壓縮失敗 
            fail: function(err) {
                console.error(err);
            },
            // 壓縮結束(不論成功失敗)
            always: function() {
                console.log('壓縮結束');
            },
            // 壓縮成功
            done: function (results) {
                $("#"+id).show();
                $("#"+id).attr("src",results.base64);
                moveSwitch = false;
                $("#buttonId").hide();
                $("#resetId").show();
            }           
        }); 
    }  

    /**旋轉**/ 
    ics.prototype.rotate=function(arr){
        if(!moveSwitch){
            alert('請點擊重置按鈕');
            return; 
        }
        imgRotate(arr); 
    } 

    /**
     * 旋轉圖片並繪製矩形框 
     */  
    function imgRotate(arr){ 
        clearCanvas();     
        if(n== null) n=0;
        if(arr=='left'){   
            (n==0)? n=3:n--;
        }else if(arr=='right'){
            (n==3)? n=0:n++;
        }
        switch(n) {  
        default :  
        case 0 : 
            canvas.width = canvasW;
            canvas.height = canvasH; 
            tempContext.rotate(0 * Math.PI / 180);
            tempContext.drawImage(imageObj, 0, 0,canvasW,canvasH);
            createCanvas(canvasW,canvasH);  
            break;  
        case 1 :
            canvas.width = canvasH;
            canvas.height = canvasW;  
            tempContext.rotate(90 * Math.PI / 180);
            tempContext.drawImage(imageObj, 0, -canvasH,canvasW,canvasH);
            createCanvas(canvasH,canvasW);     
            break;   
        case 2 :
            canvas.width = canvasW;
            canvas.height = canvasH;  
            tempContext.rotate(180 * Math.PI / 180);
            tempContext.drawImage(imageObj, -canvasW, -canvasH,canvasW,canvasH);
            createCanvas(canvasW,canvasH); 
            break;
        case 3 :
            canvas.width = canvasH;
            canvas.height = canvasW;  
            tempContext.rotate(270 * Math.PI / 180);
            tempContext.drawImage(imageObj, -canvasW, 0,canvasW,canvasH);
            createCanvas(canvasH,canvasW);
            break;        
        };     
    } 

    /**
     * 將旋轉過後的畫布內容取出來並重新創建畫布 
     * @param {Object} w 畫布的寬
     * @param {Object} h 畫布的高
     */
    function createCanvas(w,h){
        /**得到旋轉後的img對象 —— BUG 在獲取到img後,旋轉就錯亂了**/ 
        var data = tempContext.getImageData(0,0,w,h);
        tempContext.clearRect(0, 0, w,h);   
        /**重設畫布的寬高**/  
        canvasH = h;canvasW =w;    
        imgW = w, imgH = h;   
        /**將旋轉後的得到的圖片覆蓋以前的畫布**/ 
        canvas = document.getElementById("myCanvas");
        canvas.width = w; 
        canvas.height = h; 
        tempContext = canvas.getContext("2d");  
        tempContext.globalAlpha = 1; 
        tempContext.putImageData(data,0,0); 
        var img = new Image();    
        img.src = canvas.toDataURL();   
        imageRotate = img;  
        tempContext.globalAlpha=0.7;      
        tempContext.fillStyle='#F8F8F8';        
        tempContext.fillRect(oX, oY,width,height);
    }  


    /**縮放**/
    ics.prototype.scale=function(type){
        if(!moveSwitch){
            alert('請點擊重置按鈕');
            return; 
        }
        if(type=="BIG"){
            imgW = imgW + 10;
            imgH = imgH + 10/imgW*imgH;
        } else { 
            imgW = imgW - 10;  
            imgH = imgH - 10/imgW*imgH;  
        }  
        loadImgRect(oX,oY);  
    }        
    return ics;     
})();  

/*** 加載按鈕  */
        function demo_report() {
            var li = document.createElement('li');
            li.className = 'item';
            li.innerHTML = $("#anniuDiv").html(); 
            var ul = document.createElement('ul');
            ul.appendChild(li);  
            document.getElementById("canvasDivId").appendChild(ul); 
            $("#buttonId").click(function(){ 
                ics.getImageData("cutImgId");  
            }); 
            $("#rotateLeft").click(function(){
                ics.rotate("left"); 
            }); 
            $("#rotateRight").click(function(){
                ics.rotate("right"); 
            });  
            $("#little").click(function(){
                ics.scale("BIG");     
            });
            $("#scale").click(function(){
                ics.scale("little");   
            });   
            $("#affirmId").click(function(){
                ics.getImageData("cutImgId");  
            });
            $("#resetId").click(function(){
                if(confirm("您確定要重置嗎?")){
                    window.location.reload();
                }
            });
        } 

源代碼下載:點擊下載

發佈了194 篇原創文章 · 獲贊 736 · 訪問量 145萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章