要在任意轴上旋转 SVG 对象,您需要两个转换:(translate设置轴)和rotate. 你真正想要的是先translate完全应用然后旋转已经移动的元素,但它看起来是独立和同时操作的translate。rotate这在正确的位置结束,但动画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>元素,它将摆动,但如果您rotate将g.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 上实现此功能的代码,请参阅此 fiddle。rect
*以上代码的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 + ")");