我正在尝试使用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
(点击移动开始转换)
最佳答案 这是D3标准插值变换属性值的预期行为.众所周知,transform属性很难转换,因为它的值可能包含一个复杂的转换定义列表,它可能以任何顺序出现,甚至可能在一个列表中出现多次.例如:
transform="translate(100) rotate(30, 100, 100) scale(2.5) translate(-10, -50) skewX(20)"
为了能够在这些值之间转换,transition.attr()
函数在插入变换属性的值时使用d3.interpolateTransformSvg(a, b)
.这样做如下:
>在模块d3-interpolate的内部函数parseSvg()
中,通过调用接口SVGTransformList
的.consolidate()来简化变换定义列表.
>使用私有函数decompose()
,然后将此合并变换分解为其值,用于平移,旋转,倾斜和缩放.
我已经描述了在answer到“Replacing d3.transform in D3 v4”中分解变换列表的过程.
在转换期间,d3.interpolateTransformSvg(a,b)返回的插值器将在a和b的相应值之间插值,用于(1)平移,(2)旋转,(3)skewX和(4)缩放恰好在此order中.
这会为您留下合并的值,这些值最初可能会出乎意料.此外,它解释了为什么转换的顺序因转换而改变.要解决此问题并实现自定义转换,您必须提供自定义补间函数,该函数可以通过调用transition.attrTween()
来分配.此函数的实现在很大程度上取决于您的需求,并且超出了本答案的范围.