构建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,请点击下载

posted @ 2012-04-21 11:38  豆豆狗  阅读(10235)  评论(6编辑  收藏  举报