d3的过渡和旋转可以很好地协同工作吗?

时间:2012-09-19 12:10:47

标签: javascript rotation d3.js transition jsfiddle

与旋转相结合的过渡有奇怪的结果。

以下是我的问题:http://jsfiddle.net/emperorz/E3G3z/1/ 尝试点击每个方块以查看不同的行为。

请原谅被黑客入侵的代码,但如果我使用带有旋转的转换(以及x / y放置),那么它就会循环播放。

我试过了:

1)所有在变换中(旋转然后翻译),这看起来大多没问题。有点不稳定。

2)只需在变换中旋转,使用x / y属性定位。飞到各处,但最终到达正确的位置。非常奇怪。

3)变换中的所有内容(平移然后旋转),飞走,并最终进入(完全)错误的位置。

嗯。奇怪。

是否有正确的方法来旋转带有过渡的形状?

直观地说,如果第二种选择有效,那就太好了。

由于

2 个答案:

答案 0 :(得分:6)

要在任意轴上旋转SVG对象,您需要两个转换:translate(设置轴)和rotate。您真正想要的是首先完全应用translate,然后旋转已移动的元素,但translaterotate似乎独立且同时运行。这在正确的位置结束,但动画translate基本上是在旋转期间移动轴,从而产生摆动。您可以将translaterotate隔离,使它们出现在SVG元素层次结构中的不同位置。例如,看看以下内容:

<g class="outer">
    <g class="rect-container">
        <rect class="rotate-me" width=200 height=100 />
    </g>
</g>

您可以使用<rect>translate (-100, -50)置于(0,0)上。如果将旋转应用于<rect>元素,它将会抖动,但如果您rotate g.rect-container元素,它将会干净地旋转。如果要进一步重新定位,缩放或以其他方式转换元素,请在g.outer上执行此操作。而已。您现在可以完全控制变换。

找到<rect>的中心很容易,但找到<path><g>等的中心要困难得多。幸运的是,.getBBox()方法提供了一个简单的解决方案(CoffeeScript中的代码;请参阅下面的JavaScript版本*):

centerToOrigin = (el) ->
    boundingBox = el.getBBox()
    return {
        x: -1 * Math.floor(boundingBox.width/2),
        y: -1 * Math.floor(boundingBox.height/2) 
    }

现在,您可以通过传递非包装元素(使用D3的.node()方法)来居中您的元素/组

group = d3.select("g.rotate-me")
center = centerToOrigin(group.node())
group.attr("transform", "translate(#{center.x}, #{center.y})")

对于使用重新定位和缩放see this fiddle<rect>的{​​{1}}和<g>来实现此目的的代码,{{3}}。


*以上代码的Javascript:

rect

答案 1 :(得分:0)

iirc translate相对于0,0而旋转是围绕对象的中心点

因此,因为您的形状偏离0,0(例如100,200或200,100),所以它们在翻译时最终会迁移。这可以通过将Diamond3的偏移更改为[50,50]来看到 - 围绕屏幕的迁移小得多

解决方案是将0,0点重新定位到钻石的中心。在D3中有一种方法可以做到这一点 - 但是我无法记住它在我的头脑中是什么:(