SVG:反转父变换上的子对象旋转

SVG: reverse children rotation on parent transform

本文关键字:对象 旋转 变换 SVG      更新时间:2023-09-26

我在这个plunker中摆弄D3.js。它主要做我想做的事,但我注意到有一点不一致。

其思想是第二个滑块旋转容器中的SVG元素。由于其中的元素实际上是text元素,我希望将它们显示为未旋转,因此,我使用滑块中的对称值将transform: rotate应用于它们。

尽管如此,我注意到通过这样做,text元素不会围绕它们的中心旋转,而是围绕它们的左上角旋转(我认为)。当观察边附近的点并查看in如何在旋转时转置边时,这一点最为明显。

我已经尝试在这些元素上将text-anchoralignment-baseline都设置为middle,希望它能偏移text路径,但显然它不会改变它们旋转时的枢轴点。

此外,如果我尝试用轴心点坐标设置rotate,它会将一些translate应用到元素上,从而完全混淆效果,我无法理解。

不确定getBBox()是否能在这方面对我有所帮助,但我已经考虑过可能将这些点的宽度/高度偏移一半。不过,这似乎有点复杂,我希望能有一个更简单/更优雅/更干净的解决方案。

有什么想法吗?

好吧,这很尴尬。在我发布了这个问题之后,我在D3.js文档中找到了答案:polygon.centroid().

基本上,我使用该函数的返回值作为transform: rotate轴点坐标,并处理偏移。示例(上面plunker的第99行,rotate()函数):

(...)
var textElement = d3.select(this);
return justTranslate+"rotate("+ -value+ textElement.centroid() +")";
(...)

希望这能帮助到任何有同样问题的人。

编辑:由于某种原因,Chrome的控制台显示:

未捕获的类型错误:textElement.centroid不是函数

但这种行为正是我想要的。不知道为什么。

EDIT2:最终将上述答案更改为getBBox()方法,因为之前的编辑错误导致滑块移动中断。

更改为:

text.attr("transform", function(d){
    var textElement = d3.select(this);
    var current = textElement.attr("transform");
    var alreadyRotated = current.indexOf('rotate');
    var justTranslate = current.substring(0, alreadyRotated != -1 ? alreadyRotated : current.length);
    var bbox = textElement.node().getBBox();
    var point = [bbox.x + 0.5*bbox.width, bbox.y + 0.5*bbox.height];
    return justTranslate+"rotate("+ -value +" "+ point +")";
});