【问题标题】:d3 translate rotate order in transitiond3 在转换中平移旋转顺序
【发布时间】:2017-05-15 09:40:15
【问题描述】:

我正在尝试使用 d3 转换 - 我需要同时进行平移和旋转。 我有原始坐标:

let data = [
    {x: 100, y: 100, rotation: 45},
];

和 2 个矩形。一个是先平移,第二个是旋转 首先。

这是绘制矩形后产生的变换:

transform="rotate(45 115 105) translate(100, 100)"
transform="translate(100, 100) rotate(45 115 105)"

它们具有相同的平移和旋转变换,唯一不同的是它们的顺序。

然后我更改数据:

data[0].x += 30;
data[0].y += 20;
data[0].rotation += 45;

而且我希望通过这种转变得到一些转变:

transform="rotate(90 145 125) translate(130, 120)"
transform="translate(130, 120) rotate(90 145 125)"

但我真正得到的是:

transform="translate(150, 110) rotate(90)"
transform="translate(400, 100) rotate(90)"
  • 注意它改变了第一个矩形的平移旋转顺序。
  • 它还会从旋转变换中移除旋转中心(它是否在过渡期间以某种方式计算它?)
  • 它如何得到结果数字?

d3 过渡如何工作?我需要得到一些预期的结果,因为我正在尝试使用一些更高级的转换。

这是一个简单的例子:https://jsfiddle.net/pp6npw4g/2 (点击移动开始过渡)

【问题讨论】:

  • 与您的实际问题无关,但只是为了简洁、清晰和排除任何可能的错误来源:在您的 JSFiddle 中,您正在执行.attr('transform', (d) => transformFunction(d));,它只是将调用包装到transformFunction() 进入另一个匿名函数。这基本上相当于.attr('transform', transformFunction); 只是传入了对函数的引用。
  • 我知道,这只是一个例子。在实际应用程序中,我在那里做更多的事情,而不仅仅是一个函数调用。但你是对的,在这个例子中它可以被简化。
  • 没关系!只是很多人对此感到困惑。感谢它保持简单并提供一个精简的示例,而不是仅仅转储你的整个代码!
  • 由于你是围绕一个中心而不是原点旋转,你需要实现一个自定义补间函数。看看我的answer"D3 SVG transform rotation transition behaving weirdly" 了解更多详情。

标签: javascript d3.js svg transition


【解决方案1】:

这是 D3 对 transform 属性值的标准插值的预期行为。众所周知,transform 属性很难转换,因为它的值可能包含一个复杂的转换定义列表,这些定义可能以任何顺序出现,甚至可能在一个列表中出现多次。例如:

transform="translate(100) rotate(30, 100, 100) scale(2.5) translate(-10, -50) skewX(20)"

为了能够在这些值之间转换,transition.attr() 函数在插入 transform 属性值时使用 d3.interpolateTransformSvg(a, b)。这将执行以下操作:

  1. 在模块 d3-interpolate 的内部函数 parseSvg() 中,转换定义列表通过调用接口 SVGTransformList.consolidate() 来归结。

  2. 使用私有函数decompose(),然后将这个合并的变换分解为 translaterotateskew规模

我已经在answer 中描述了将转换列表分解为"Replacing d3.transform in D3 v4" 的过程。

在过渡期间,d3.interpolateTransformSvg(a, b) 返回的插值器将在 ab 的相应值之间进行插值,用于 (1) translate、(2) rotate、(3) skewX 和(4) scale 就是这个order

这为您留下了统一的价值观,起初可能会出乎意料。此外,它解释了为什么转换顺序会因转换而改变。要解决此问题并实现自定义过渡,您必须提供自定义补间函数,该函数可以通过调用transition.attrTween() 来分配。但是,此功能的实现在很大程度上取决于您的需求,并且超出了此答案的范围。

【讨论】:

  • 感谢您的解释!我会尝试使用补间函数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-17
  • 1970-01-01
  • 2013-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多