将浏览器点击事件“x”和“y”坐标转换为缩放的 Snap svg 元素上的坐标

Translating browser click event `x` and `y` coordinates to coordinates on a scaled Snap svg element

我需要在用户点击的位置向 snap 渲染的 svg 添加一段文本。

因为 SVG 使用 100% 宽度缩放并使用 viewBox 属性,我需要将浏览器点击事件提供的 xy 坐标转换为 xy 缩放 svg 上的坐标。

我使用这段代码成功完成了这项工作:

var $canvas = $('svg#myscaledsvg');
var snap = new Snap($canvas[0]);

snap.mousedown(function(event) {
    var offset = $canvas.offset();
    var matrix = snap.transform().diffMatrix.invert();

    var x = matrix.x(event.pageX - offset.left, event.pageY - offset.top);
    var y = matrix.y(event.pageX - offset.left, event.pageY - offset.top)

    // below function call actually renders the text element to the given x and y coords       
    addSomeText(x, y);
});

现在,我明白为什么我需要减去偏移量了。我不明白的是 snap.transform().diffMatrix.invert() 实际上做了什么。

有人能告诉我为什么这行得通吗?我无法从 snap 文档中获得太多信息,整体上看起来相当稀疏。

我猜在这种情况下,您可以将 diffMatrix 换成 globalMatrix,它仍然有效?

Snap 在响应 transform() 方法时存储 3 个矩阵。 localMatrix、diffMatrix 和 globalMatrix。

localMatrix 是存在于元素本身的变换

globalMatrix是从视口到正在应用的元素的矩阵

diffMatrix就是它们的差值

对于 globalMatrix,可能值得查看 getCTM,因为它传递给此本机方法。 对于 localMatrix,查看元素本身的任何变换(可能 none 对 svg 元素本身,因为它不支持变换)。

因此,当您查看浏览器时,视图可能会放大、平移等,有一个 viewBox。鼠标的坐标,需要从这个坐标 space 转换为元素所在的坐标。这就是 globalMatrix 的逆操作,从鼠标转换。所以我假设 diffMatrix 和 globalMatrix (getCTM) 在这种情况下可能意味着相同(因为它是一个没有应用转换的 svg 元素)。

如果这真的没有意义,可能值得多看看 svg 坐标 space 教程,因为它可能很有帮助。

Edit: I'm adding a bit more info to try and help below...

jsfiddle 我已经完成了,有一个使用与 OP 类似代码的示例。

jsfiddle 2 相似但响应迅速,查看控制台日志以查看矩阵比例变化

SVG基本上是按4缩放的,所以用下面的放大...

    height="800" width="800" viewBox="0 0 200 200"

    height="100%" width="100%" viewBox="0 0 200 200"

25,25处有一个圆圈,点击fiddle中的圆圈。

鼠标事件在 user/browser 事件 space 中约为 100,100(需要考虑一些偏移量,因此可能为 108,108 左右)。

所以比例为 4,我们需要将 100,100 转换为该比例,否则它会出现在屏幕之外。

如果我们将在 svg 上显示的所有内容都放大 4 倍,我们只需要使用 1/4 的值就可以在正确的坐标处显示 可能是有用的简单的看待方式。

我们如何做到这一点?我们反转比例(或任何变换)。我们真正想要的是将 100,100 转换为 25,25 的 0.25 比例,以便它出现在屏幕上的正确位置,因为所有内容都被放大了(因为所有内容都将通过 svg 参数缩放 4)。

是的,localMatrix 对 svg 元素本身并没有多大意义(但这也不是问题)。如果它是一个具有变换或其他元素的组,那将是有意义的。

还值得注意的是,Snap 将参数 x、y 传递给 mousedown 函数,因此您可能会使用它,而不是事件。pageX/pageY。