Javascript光标缩放

Javascript光标缩放,javascript,html,canvas,zooming,panning,Javascript,Html,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 Vec

是否有一种方法可以使用此代码缩放光标点?我不能动脑去做这件事。画布将缩放,但它仅从左上角放大和缩小

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);
    }
}

画布始终从当前原点开始缩放。默认原点为[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);

首先,我想指出,从您的代码来看,您似乎正在侦听画布上的“鼠标滚轮”事件。如前所述,“鼠标滚轮”活动是非标准的,不可能成为标准。因此,当你听它的时候,你得到的结果充其量是好坏参半的。几乎每个平台都可以使用“滚动”事件,这可能是捕获用户输入的更好途径

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

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

为了实现您正在寻找的“缩放”行为,必须在缩放后对上下文进行转换,以便参考点占据与缩放前相同的物理位置。在本例中,参考点是执行缩放操作时用户光标所在的点

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

  • 缩放前计算鼠标光标与画布原点的距离
  • 将该距离除以比例因子
  • 按该值转换原点
  • 由于您的代码没有指明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);
        }
    }
    

    0,0可能是左上角?-那是我的猜测