Canvas 實現圖片剪切


       用戶上傳頭像然后截圖的需求很常見,很多做法是把圖像發送到后端,把裁剪后的結果發送給瀏覽器,這種方式會增加處理時延。最近正好學習了HTML5里的canvas,發現它的圖片處理功能比較強大,就打算用canvas提供的API實現純前端的剪切。這里頭關鍵有三步:顯示未經處理的圖片,得到裁剪區域,顯示裁剪后的區域。我們分別討論:

       1. 顯示未經處理的圖片

       創建一個canvas,用drawImage(img,0,0,canvas.width,canvas.height)就可以。主要這里的img是一個Image類的object, 用new Image創建。

var img = new Image();
    img.src = "./beauty.jpg";
img.onload = function(){
        cxt1.drawImage(img,0,0,canvas1.width,canvas1.height); //一定要寫在onload回調中,否則看不到圖片
}
       2. 得到裁剪區域
        用一個position:absolute的div框來選擇裁剪區域,通過javascript提供的方法能得到該div在canvas中所處的位置(x,y),然后用getImageData(srcX,srcY,width,height)得到選擇框中的像素點。 這里需要知道,通過canvas.getBoundingClientRect().left和canvas.getBoundingClientRect().top可以得到canvas相對於瀏覽器視圖的左邊和上邊位置。
       3. 顯示裁剪后的區域
       這部分是最復雜的。假設getImageData得到了imgData, 需要創建一個canvas2,用canvas2.putImageData(imgData,0,0,canvas2.width,canvas2.height)將選擇框里的像素繪制到這個臨時的canvas2里。然后用canvas2.toDataURL("image/png")將canvas2轉為dataurl類型的圖片。有了dataurl后,就可以正常顯示裁剪后的圖片了。
 ×××××××××××××××××××××此處為分割線,算法介紹完畢××××××××××××××××××
        那么問題來了。為什么不能直接把getImageData得到的imgData通過putImageData繪制到最終要顯示的區域,而非要創建一個臨時的canvas2(不再頁面上顯示)呢?其實這是我想出來的一個折中方案。用putImageData繪制的畫布上,只能按照等比例或者更小比例顯示imgData,如果你想把剪切出來的圖片放大顯示,putImageData是不能支持的(這個結論是我經過測試發現的)。所以為了看到放大后的剪切區域(即使犧牲清晰度),就要用drawImage方法了,而drawImage的第一個參數不能是一堆像素數據,就只能用一個臨時的canvas來作為像素數據和dataurl之間的橋梁了。
       最后,上一段測試代碼(可運行):
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <style>
.mark{
    position:absolute;
    height:100px;
    width:100px;
    left:100px;
    top:180px;
    border:1px solid #000;
    cursor:move;
}
    </style>
</head>
<body>
<canvas id="c1"></canvas> //顯示原圖像
<div class="mark" id="mark"></div>
<canvas id="c3"></canvas> //顯示剪切后的圖像
<script>
    var canvas1 = document.getElementById("c1")
    var oMark = document.getElementById("mark")
    var canvas3= document.getElementById("c3")
     canvas1.height = 300;
    canvas1.width=300;
    canvas3.height=100;
    canvas3.width=100;
    var cxt1 = canvas1.getContext("2d")
    var img = new Image();
    img.src = "./beauty.jpg";
    var srcX = oMark.offsetLeft-canvas1.getBoundingClientRect().left;
    var srcY = oMark.offsetTop-canvas1.getBoundingClientRect().top;
    var sWidth = oMark.offsetWidth;
    var sHeight = oMark.offsetHeight;

    var canvas2 = document.createElement("canvas")
    var cxt2=canvas2.getContext("2d")
    img.onload = function(){
        cxt1.drawImage(img,0,0,canvas1.width,canvas1.height);
        var dataImg = cxt1.getImageData(srcX,srcY,sWidth,sHeight)
        canvas2.width = sWidth;
        canvas2.height = sHeight;
        cxt2.putImageData(dataImg,0,0,0,0,canvas2.width,canvas2.height)
        var img2 = canvas2.toDataURL("image/png");

        var cxt3=canvas3.getContext("2d")
        var img3 = new Image();
        img3.src = img2;
        img3.onload  = function(){
            cxt3.drawImage(img3,0,0,canvas3.width,canvas3.height)
        }

    }
</script>
</body>
</html>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM