SVG放大鼠标 - 数学模型

Jam*_*mes 7 javascript css svg

在你想到"为什么这个人在这个问题上寻求帮助之前,肯定已经实现了1000x" - 虽然你大部分都是正确的,但我试图用几个开源库来解决这个问题,但我在这里.

我试图从头开始实现基于SVG的"放大鼠标滚轮,专注于鼠标".

我知道有很多库可以完成这个,d3和svg-pan-zoom来命名一对.不幸的是,我使用这些库的实现不符合我的期望.我希望我可以从社区获得这种UI功能的基础数学模型的帮助.

基本上,期望的行为就像谷歌地图,用户将鼠标悬停在某个位置,他们滚动鼠标滚轮(向内),地图图像的比例增加,而悬停的位置变为水平和垂直中心的视口.

当然,我可以访问视口的宽度/高度和鼠标的x/y.

在这个例子中,我将只关注x轴,视口是900单位宽,正方形是100单位宽,它的x偏移是400单位,比例是1:1

<g transform="translate(0 0) scale(1)">
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

假设鼠标x位置处于或接近450个单位,如果用户轮到直到比例达到2:1,我预计x偏移量将达到-450个单位,以焦点为中心.

<g transform="translate(-450 0) scale(2)">
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

需要在每个轮滚动增量上重新计算x和y偏移,作为当前比例/鼠标偏移的函数.

我的所有尝试都完全没有达到预期的行为,任何建议都值得赞赏.

虽然我感谢任何帮助,但请不要回答对第三方库,jQuery插件和那种性质的东西的建议.我的目的是从一般意义上理解这个问题背后的数学模型,我对SVG的使用主要是说明性的.

Arj*_*jan 8

我通常做的是保持三个变量偏移x偏移y和比例.它们将作为变换应用于容器组,就像元素一样<g transform="translate(0 0) scale(1)">.

如果鼠标位于原点之上,则新的翻译将很容易计算.您只需将偏移量x和y乘以比例差:

offsetX = offsetX * newScale/scale
offsetY = offsetY * newScale/scale
Run Code Online (Sandbox Code Playgroud)

你可以做的是平移偏移量,使鼠标位于原点.然后你缩放,然后你翻译每件事.看看这个有一个scaleRelativeTo方法的typescript类来做你想做的事情:

export class Point implements Interfaces.IPoint {
    x: number;
    y: number;

    public constructor(x: number, y: number) {
      this.x = x;
      this.y = y;
    }

    add(p: Interfaces.IPoint): Point {
      return new Point(this.x + p.x, this.y + p.y);
    }

    snapTo(gridX: number, gridY: number): Point {
      var x = Math.round(this.x / gridX) * gridX;
      var y = Math.round(this.y / gridY) * gridY;
      return new Point(x, y);
    }

    scale(factor: number): Point {
      return new Point(this.x * factor, this.y * factor);
    }

    scaleRelativeTo(point: Interfaces.IPoint, factor: number): Point {

      return this.subtract(point).scale(factor).add(point);
    }

    subtract(p: Interfaces.IPoint): Point {
      return new Point(this.x - p.x, this.y - p.y);
    }

  }
Run Code Online (Sandbox Code Playgroud)

因此,如果您已经给出了变换,translate(offsetX,offsetY) scale(scale)并且在(mouseX, mouseY)导致新比例时发生滚动事件,newScale您将通过以下方式计算新变换:

offsetX = (offsetX - mouseX) * newScale/scale + mouseX
offsetY = (offsetY - mouseY) * newScale/scale + mouseY
Run Code Online (Sandbox Code Playgroud)