構建Canvas矢量圖形渲染器(三)—— 鼠標拖動平移、滾輪縮放


上次隨筆實現了用button點擊進行縮放,平移;用戶操作感很差。本次隨筆接着上次的內容進行鼠標拖拽、縮放。

先上demo,鼠標滾輪縮放、拖拽平移。

 

1.何為控制類?control

    控制類是添加在圖層類上用於控制圖層的各種操作的類型,比如我們今天所講了的鼠標滾輪縮放、鼠標拖拽就屬於兩個控制類。

1.首先看滾輪縮放

//CLASS: 縮放控制類
function Scale(layer) {
    this.layer = layer;
    this.div = layer.div;
    this.active();
}

Scale.prototype.wheelChange = function(e) {
    var layer = this.layer;
    var delta = (e.wheelDelta / 120) * 30;
    var deltalX = layer.size.w/2 - (e.offsetX || e.layerX);
    var deltalY = (e.offsetY || e.layerY) - layer.size.h/2;
    
    var px = {x: (e.offsetX || e.layerX), y:(e.offsetY || e.layerY)};
    var zoomPoint = this.layer.getPositionFromPx(px);    
    var zoom = this.layer.zoom + delta;
    var newRes = this.layer.getResFromZoom(zoom);
    
    var center = new CanvasSketch.Position(zoomPoint.x + deltalX * newRes, zoomPoint.y + deltalY * newRes);
    
    
    this.layer.moveTo(zoom, center);
    
    CanvasSketch.stopEventBubble(e);
}

Scale.prototype.DOMScroll = function(e) {
    CanvasSketch.stopEventBubble(e);
}

Scale.prototype.Events = [["mousewheel", Scale.prototype.wheelChange],["DOMMouseScroll", Scale.prototype.DOMScroll]];

Scale.prototype.active = function () {
    for(var i = 0, len = this.Events.length; i < len; i++) {
        var type = this.Events[i][0];
        var listener = this.Events[i][1];
        listener = CanvasSketch.bindAsEventListener(listener, this);
        this.div.addEventListener(type, listener, true);        
    }
}

    1.在Scale類Layer作為構造函數的參數。

    2.這里有一個Events常量屬性,是一個二維數組保存着這個controls類所監聽的事件和回調函數。

    3.avtive方法,用於激活監聽。

    4.最重要的當然還是回調函數wheelChange;每次所滾動滾輪改變的zoom為30%,通過當前的鼠標位置計算出當前指定的世界坐標系位置(zoomPoint),並通過鼠標的偏移量和新的res計算出我們縮放的中心點。最后我們還要阻止事件冒泡、並阻止瀏覽器的默認事件,我們當然不希望在縮放的時候把瀏覽器的頁面向下滾動了吧!

2.如何阻止事件冒泡和瀏覽器默認事件

//阻止事件冒泡
CanvasSketch.stopEventBubble = function(e) {
    if (e.preventDefault) {
        e.preventDefault();
    } else {
        e.returnValue = false;
    }

    if (e && e.stopPropagation)
        e.stopPropagation();
    else
        window.event.cancelBubble=true;
}

    這個函數的上半部分是阻止瀏覽器的默認事件,比如說:滾輪滾動頁面,左鍵點擊並移動鼠標顯示為光標狀態等等、、。

3.下面再看看平移拖動。

//CLASS:控制平移。
function Pan(layer) {
    this.layer = layer;
    this.div = layer.div;
    this.active();
    this.dragging = false;
}

Pan.prototype.startPan = function(e) {
    this.dragging = true;
    //在一開始保存點擊的位置。
    this.lastX = (e.offsetX || e.layerX);
    this.lastY = (e.offsetY || e.layerY);
    //設置鼠標樣式。
    this.layer.div.style.cursor = "move";
    CanvasSketch.stopEventBubble(e);
}

Pan.prototype.pan = function(e) {
    if(this.dragging) {
        var layer = this.layer;
        //計算改變的像素值
        var dx = (e.offsetX || e.layerX) - this.lastX;
        var dy = (e.offsetY || e.layerY) - this.lastY;
        this.lastX = (e.offsetX || e.layerX);
        this.lastY = (e.offsetY || e.layerY);
        layer.center.x -= dx * layer.res;
        layer.center.y += dy * layer.res;
        layer.moveTo(layer.zoom, layer.center);
    }
    CanvasSketch.stopEventBubble(e);
}

Pan.prototype.endPan = function(e) {
    this.layer.div.style.cursor = "default";
    this.dragging = false;
    CanvasSketch.stopEventBubble(e);
}

Pan.prototype.Events = [["mousedown", Pan.prototype.startPan],
                        ["mousemove", Pan.prototype.pan],
                        ["mouseup", Pan.prototype.endPan]];

                        
Pan.prototype.active = function () {
    for(var i = 0, len = this.Events.length; i < len; i++) {
        var type = this.Events[i][0];
        var listener = this.Events[i][1];
        listener = CanvasSketch.bindAsEventListener(listener, this);
        this.div.addEventListener(type, listener, true);        
    }
}                

    1.平移拖動監聽了三個鼠標事件:鼠標按下、鼠標平移、鼠標彈起;在這三個事件當中我們做了分別如下的處理:

    a.在鼠標按下的時候我們開啟拖拽(dragging設為true),並記錄初始的鼠標位置。

    b.在鼠標平移時候我們首先判斷是否出去拖拽狀態;之后與初始位置比較計算偏移的該變量,並換算為世界坐標系長度找到新的center調用layer.moveTo;最后將當前位置設置為初始位置。

    c.在鼠標彈起時候做的處理就比較少了。就是關閉拖拽狀態(dragging設為false)。

    好了,本次隨筆就先寫這些,大家可以下載源碼看看里面的結構是怎么樣的。

    下次預告: 1.添加線的矢量元素。

                   2.添加面矢量元素。

    本次隨筆的所有源碼+demo,請點擊下載


免責聲明!

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



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