背景
我喜欢 SVG2 中扩展的 CSS 支持。不必一遍又一遍地重写属性真是太好了。所以我一直在将项目中的一些代码从 SVG 属性转换为 CSS。其中大部分工作都很好。
当涉及到转换时,如果您对 CSS 转换在 HTML 中的工作方式感到满意,那么事情看起来会很棘手。(对于转换尤其如此rotate()
,这是这个问题的重点。)这是因为 SVG 没有 HTML 所具备的“自动流程”。
换句话说,当你有一堆 HTML 元素,一个接一个,它们会自动按照盒子模型进行布局。
SVG 中没有这样的“自动”或“默认”布局。因此,SVG 转换默认是从原点计算的。(这是0,0
在用户坐标中)。
几乎完美的解决方案
对于大多数元素,有一个简单的解决方案:很棒的 CSS 属性transform-box
。在大多数情况下,使用以下 CSS 将允许您以与 HTML 元素几乎相同的方式转换 SVG 元素:
/* whatever elements you want to transform */
rect, polygon {
transform-box: fill-box;
transform-origin: center center; /* or `top left`, `center right`, etc. */
}
.rotate90 {
transform: rotate(90deg);
}
现在,您可以执行类似...
<rect class="rotate90" x="123" y="789" width="50" height="50" />
它将围绕transform-origin
CSS 中指定的旋转。由于上面的示例使用 a transform-origin
of center center
,因此它在原地旋转。
这与使用transform: rotate(…)
. 而且——特别是如果 SVG 图像中有很多这样的旋转——它比等效的 SVG 标记要好得多。
为什么 CSS 比等效的 SVG 标记更好?
因为SVG 的rotate()
函数语法略有不同,没有与transform-box: fill-box
上面使用的 CSS 等效的语法,除非您为每次旋转指定 X 和 Y 坐标。
这意味着您必须每次都输入旋转点,如下所示:
<rect x="123" y="789" width="50" height="50"
transform="rotate(90 123 789)"
></rect>
<!--
In this example, the rotation pivots around the X and Y coordinates of the `rect` element.
If you wanted to rotate around the center, you would have to calculate:
x + width/2
y + width/2
And use those values in the `rotate()` function instead.
-->
问题
我遇到的问题是CSS 解决方案不适用于<use />
元素。
原因很清楚:<use />
元素将引用的元素克隆到新位置。因此,就 CSS 而言,它正在转换<use />
元素,而不是克隆的 (Shadow-DOM) 内容。
当涉及到将 CSS 应用于其他挑战时<use />
——例如设置不同的配色方案——有一些解决方案(比如来自 SVG 超级英雄 Sara Soueidan的解决方案)。
但是当谈到解决坐标问题时,我还没有找到解决方法。
示例代码
编辑:为了更明确地说明我的目标,这里有一些示例代码。
.transform-tl,
.transform-tc,
.transform-tr,
.transform-cl,
.transform-cc,
.transform-cr,
.transform-bl,
.transform-bc,
.transform-br {
transform-box: fill-box;
}
.transform-tl { transform-origin: top left; }
.transform-tc { transform-origin: top center; }
/*
…and so on, for the other combinations of `transform-origin` keyword values…
*/
.rotate90.cw {
transform: rotate(90deg)
}
.rotate90.ccw {
transform: rotate(-90deg)
}
<!--
Using the CSS classes in the following manner works as intended for most SVG elements as intended.
But with the `<use />` element, the rotation does not pivot around the top left corner, as expected... :(
-->
<use
class="transform-tl rotate90 cw"
x ="0"
y ="1052"
href ="#block-A12-2"
></use>
(感谢@PaulLeBeau 推动包含这段代码。)
有没有人有办法解决吗?
(即使是一个变通的解决方案——只要它比transform
在每个上指定 SVG 属性所涉及的重复更少<use />
——也会受到欢迎!)