上次隨筆實現了用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,請點擊下載。
