要在任意轴上旋转 SVG 对象,您需要两个转换:translate(设置轴)和rotate。您真正想要的是首先完全应用translate,然后旋转已经移动的元素,但似乎translate 和rotate 独立且同时运行。这在正确的位置结束,但是为translate 设置动画实际上是在旋转期间移动轴,从而产生摆动。您可以将translate 与rotate 隔离开来,方法是让它们出现在SVG 元素层次结构中的不同位置。例如,看看以下内容:
<g class="outer">
<g class="rect-container">
<rect class="rotate-me" width=200 height=100 />
</g>
</g>
您可以使用translate (-100, -50) 将<rect> 居中在(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})")
对于在单个 <rect> 和 <g> 中的 2 个 rects 上实现此功能并进行重新定位和缩放的代码,see this fiddle。
*以上代码的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 + ")");