1. 程式人生 > >使用HTML5 canvas 標籤進行圖片裁剪、旋轉、縮放

使用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.onload=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();
                }
            });
        } 

原始碼下載:點選下載