Javascript游标缩放

时间:2014-11-14 19:24:36

标签: javascript html5 canvas zooming panning

有没有办法使用此代码缩放光标点?我无法理解这一点。画布放大但只从左上角放大和缩小。

var previousMousePosition = new Vector(0, 0);
function OnMouseWheel (event) {
    var delta = event.wheelDelta ? event.wheelDelta/40 : event.detail ? -event.detail : 0;
    var mousePosition = new Vector(event.clientX, event.clientY);
    var scaleFactor = 1.1;  
    if (delta) {
        var factor = Math.pow(scaleFactor,delta);
        context.scale(factor,factor);
    }
}

2 个答案:

答案 0 :(得分:1)

画布总是从它的当前原点缩放。默认原点为[0,0]。

如果您想从另一个点扩展,可以先context.translate(desiredX,desiredY);。这会将画布的原点重置为[desiredX,desiredY]。

这样,您的context.scale将从指定的来源缩放。

由于所有上下文转换对于每个后续绘图都保持有效,因此在完成当前绘图后,您经常需要反转变换(=='重置'用于下一个绘图,可能/可能不会使用当前的转换)。要进行转换,只需使用否定参数调用转换:例如。 context.scale(-factor,-factor)。转换应该按照原始转换的相反顺序进行。

所以你重构的代码可能是:

// set the origin to mouse x,y
context.translate(mousePosition.x,mousePosition.y);

// scale the canvas at x,y
context.scale(factor,factor);

// ...draw stuff

// reverse the previous scale
context.scale(-factor,-factor);

// reverse the previous translate
context.translate(-mousePosition.x,-mousePosition.y);

答案 1 :(得分:0)

首先,我想指出,从您的代码中看起来您正在监听画布上的'mousewheel'事件。如上所述here,“鼠标滚轮”事件是非标准的,无法成为标准。因此,在收听时,您最多会得到混合的结果。 “滚动”事件几乎在每个平台上都可用,并且可能是捕获用户输入的更好途径。

就你的问题而言,你正在寻找你正在寻找的行为,但你错过了一步。

当您在画布上下文对象上调用scale时,行为非常简单。从左上角(0,0)开始,该方法根据提供的因子缩放画布的点。假设您有一个10x10的画布,以及一个1,1点的黑点。如果画布在两个轴上按比例缩放2,则0,0点将保持在同一位置,但点1,1将是缩放前点2,2的位置。

为了实现您正在寻找的“缩放”行为,缩放后的上下文必须已翻译,以便参考点占用与缩放前相同的物理位置。在您的情况下,参考点是执行缩放操作时用户光标所在的点。

幸运的是,canvas上下文对象提供了一个translate(x,y)方法,可以相对于画布的0,0点移动上下文的原点。要将其翻译为正确的ammount,您必须:

  1. 在缩放前计算鼠标光标距画布原点的距离
  2. 将该距离除以比例因子
  3. 按该值翻译原点
  4. 由于您的代码未指明HTML的结构,因此我在下面标记了一些注释和伪代码,以说明如何实现此算法:

    //You'll need to get a reference to your canvas in order to calculate the relative position of
    //the cursor to its top-left corner, and save it to a variable that is in scope inside of your
    //event handler function
    
    var canvas = document.getElementById('id_of_your_canvas');
    
    //We're also going to set up a little helper function for returning an object indicating
    //the position of the top left corner of your canvas element (or any other element)
    
    function getElementOrigin(el){
        var boundingBox = el.getBoundingClientRect();
        return { x: boundingBox.left, y: boundingbox.top};
    }
    
    function OnMouseWheel (event) {
        //you probably want to prevent scrolling from happening or from bubbling so:
        event.preventDefault();
        event.stopPropagation();
    
        var delta = event.wheelDelta ? event.wheelDelta/40 : event.detail ? -event.detail : 0;
    
        var canvasCorner  = getElementOrigin(canvas)
        //JavaScript doesn't offer a 'vector' or 'point' class natively but we don't need them 
        var mousePosition = {x: event.clientX, y: event.clientY};
        var diff = {x: mousePostion.x - canvasCorner.x, y: mousePosition.y - canvasCorner.y};
        var scaleFactor = 1.1;  
    
        if (delta) {
            var factor = Math.pow(scaleFactor,delta);
            var transX = (-1/factor) * diff.x;
            var transY = (-1/factor) * diff.y;
            context.scale(factor,factor);
            context.translate(transX, transY);
        }
    }