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的使用主要是说明性的.
我通常做的是保持三个变量偏移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)