2

与旋转相结合的过渡会产生奇怪的结果。

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

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

我试过了:

1) 全部在变换中(旋转然后平移),这看起来基本没问题。有点摇摇晃晃。

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

3)所有在变换(平移然后旋转),飞走,并最终在(完全)错误的地方。

嗯。奇怪的。

是否有使用过渡旋转形状的正确方法?

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

谢谢

4

2 回答 2

6

要在任意轴上旋转 SVG 对象,您需要两个转换:(translate设置轴)和rotate. 你真正想要的是先translate完全应用然后旋转已经移动的元素,但它看起来是独立和同时操作的translaterotate这在正确的位置结束,但动画translate基本上是在旋转过程中移动轴,从而产生摆动。您可以通过让它们出现在 SVG 元素层次结构中的不同位置translate来隔离它们。rotate例如,看看以下内容:

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

您可以使用 将<rect>(0,0)居中translate (-100, -50)。如果您将旋转应用于<rect>元素,它将摆动,但如果您rotateg.rect-container元素旋转,它将完全旋转。如果您想重新定位、缩放或以其他方式进一步转换元素,请继续g.outer。就是这样。您现在可以完全控制您的变换。

找到 a<rect>的中心很容易,但要找到 a <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})")

对于通过重新定位和缩放在单个<rect><g>2 s 上实现此功能的代码,请参阅此 fiddlerect


*以上代码的Javascript:

var center, centerToOrigin, group;

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

group = d3.select("g.rotate-me");
center = centerToOrigin(group.node());
group.attr("transform", "translate(" + center.x + ", " + center.y + ")");
于 2013-02-14T20:59:33.283 回答
0

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

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

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

于 2012-09-19T13:24:27.163 回答