1. 程式人生 > >Canvas:橡皮筋線條繪製

Canvas:橡皮筋線條繪製

Canvas:橡皮筋線條繪製

效果演示

實現要點

事件監聽

【說明】:

在Canvas中檢測滑鼠事件是非常簡單的,可以在canvas中新增一個事件監聽器,當事件發生時,瀏覽器就會呼叫這個監聽器。

我們可以使用繫結事件屬性:

canvas.onmousedown = function(e)
{
   //.....
}  

此外,也可以使用更為通用的addEventListener()方法來註冊監聽器:

canvas.addEventListener('mousedown',function(e){
   //..... 
})  

注意:使用onmouseXXX更為簡單,但是addEventListener()可以向某個事件註冊多個監聽器。

滑鼠座標轉換為canvas座標

【說明】

  瀏覽器通過事件物件傳遞給監聽器的滑鼠座標,是視窗座標,而不是相對於canvas自身的座標。大部分情況下,我們需要知道的是發生滑鼠事件的點相對於canvas的位置,而不是在整個視窗中的座標,所以必須進行座標轉換

【例項】:轉換程式碼

    function windowToCanvas(x, y) {
        var bbox = canvas.getBoundingClientRect();
        return {
            x: (x - bbox.left)*(canvas.width / bbox.width),
            y: (y - bbox.top)*(canvas.height / bbox.height)
        };
    }

注意:為什麼最後要乘(canvas.width / bbox.width),我們簡單說明一下,canvas存在元素大小與繪圖表面大小兩套尺寸,我們的影象是顯示在繪圖表面上的,但是如果canvas元素大小較大的話,瀏覽器就會對繪圖表面上的影象進行縮放以適應canvas元素大小,我們要避免這種縮放就要除去縮放比例

我們用element表示canvas元素,用canvas表示繪圖表面,src表示繪製的內容,dest表示展示的內容

縮放規則為:dest.size = src.size * (element.size / canvas.size)

所以,src=dest.size*(canvas.size/element.size)

 繪製表面的儲存與恢復

【說明】:

  使用getImageData與putImageData方法來儲存與恢復繪圖環境的繪圖表面數據。

【例項】:儲存和恢復資料

    function saveDrawingSurface() {
        drawingSurfaceImageData = context.getImageData(0, 0, canvas.width, canvas.height);
    }

    function restoreDrawingSurface() {
        context.putImageData(drawingSurfaceImageData, 0, 0);
    }  

實現程式碼

<canvas id="canvas"></canvas>

<div id="controls">
    <select id="strokeStyleSelect">
        <option value="red">red</option>
        <option value="green">green</option>
        <option value="blue">blue</option>
    </select>
</div>
GuideWires:
<input id="guidewireCheckbox" type="checkbox" checked>
<input id="eraseAllButton" type="button" value="Erase All">


<script type="text/javascript">
    var canvas = document.getElementById("canvas");
    var context = canvas.getContext('2d');
    var eraseAllButton = document.getElementById("eraseAllButton");
    var strokeStyleSelect = document.getElementById("strokeStyleSelect");
    var guidewireCheckbox = document.getElementById("guidewireCheckbox");
    var drawingSurfaceImageData;
    var mousedown = {};
    var rubberbandrect = {};
    var dragging = false;
    guidewires = guidewireCheckbox.checked;

    function windowToCanvas(x, y) {
        var bbox = canvas.getBoundingClientRect();
        return {
            x: (x - bbox.left)* (canvas.width / bbox.width),
            y: (y - bbox.top)* (canvas.height / bbox.height)
        };
    }

    function saveDrawingSurface() {
        drawingSurfaceImageData = context.getImageData(0, 0, canvas.width, canvas.height);
    }

    function restoreDrawingSurface() {
        context.putImageData(drawingSurfaceImageData, 0, 0);
    }

    function updateRubberbandRectangle(loc) {
        rubberbandrect.width = Math.abs(loc.x - mousedown.x);
        rubberbandrect.height = Math.abs(loc.y - mousedown.y);
        if (loc.x > mousedown.x)
            rubberbandrect.left = mousedown.x;
        else
            rubberbandrect.left = loc.x;
        if (loc.y > mousedown.y)
            rubberbandrect.top = mousedown.y;
        else
            rubberbandrect.top = loc.y;
    }

    function drawRubberbandShape(loc) {
        context.beginPath();
        context.moveTo(mousedown.x, mousedown.y);
        context.lineTo(loc.x, loc.y);
        context.stroke();
    }

    function updateRubberband(loc) {
        updateRubberbandRectangle(loc);
        drawRubberbandShape(loc);
    }

    canvas.onmousedown = function (e) {
        var loc = windowToCanvas(e.clientX, e.clientY);
        e.preventDefault();
        saveDrawingSurface();
        mousedown.x = loc.x;
        mousedown.y = loc.y;
        dragging = true;
    };

    canvas.onmousemove = function (e) {
        var loc;
        if (dragging) {
            e.preventDefault();
            loc = windowToCanvas(e.clientX, e.clientY);
            restoreDrawingSurface();
            updateRubberband(loc);
        }
    };

    canvas.onmouseup = function (e) {
        loc = windowToCanvas(e.clientX, e.clientY);
        restoreDrawingSurface();
        updateRubberband(loc);
        dragging = false;
    };
    context.strokeStyle = "red";
</script>