为什么不将 translate(${x},${y}) 和 translate(${-x},${-y}) 抵消?

Why don't translate(${x},${y}) and translate(${-x},${-y}) cancel out?

这是 https://observablehq.com/@d3/non-contiguous-cartogram 的一个片段,它控制状态形状的转换。

function transform(d, year) {
  const [x, y] = path.centroid(d);
  return `
    translate(${x},${y})
    scale(${Math.sqrt(data.get(d.id)[year])})
    translate(${-x},${-y})
  `;
}

既然xy是常量,难道translate(${x},${y})translate(${-x},${-y})不应该抵消吗?

此外,为什么这种机制可以将质心固定在原来的位置?

了解 SVG 转换是连续应用的很重要,即顺序很重要。您不能只是将数字相加来合并各种转换定义的列表。用spec的话来说:

The value of the ‘transform’ attribute is a <transform-list>, which is defined as a list of transform definitions, which are applied in the order provided.

该列表的每个变换定义都操纵作为所有后续变换基础的坐标系。尽管在您的示例中,平移名义上在相反方向上的数量相同,但它们不会抵消,因为在两者之间发生的缩放会沿途改变坐标系。因此,第二个翻译没有覆盖与第一个相同的距离。

要理解为什么这些变换将质心保持在原位,将它们更正式地写下来会很有帮助。给定质心的坐标 (xc, yc) 和比例因子 k 我们可以将它们写成:

xxc + k (xxc)
yyc + k (yyc)

每个原点(x, y)映射到质心(第一项)然后向外移动到它的原始位置,但它只移动了一个缩小的部分原始距离(第二项)。

将质心本身插入这些规则显示第二项抵消,从而使质心保持在其原始位置,从而使整个变换以质心为中心:

xcxc + k (xcxc) = xc
ycyc + k (ycyc) = yc