Zea*_*rin 2 css svg css-transforms shadow-dom svg-transforms
我\xe2\x80\x99m 喜欢 SVG2 中扩展的 CSS 支持。不用一遍又一遍地重写属性,这很好。所以我\xe2\x80\x99一直在将项目中的一些代码从SVG属性转换为CSS。其中大部分效果都很好。
\n当谈到转换时,如果您熟悉 CSS 转换在 HTML 中的工作方式,那么事情可能会显得很棘手。(这对于rotate()转换尤其如此,这是这个问题的焦点。) \xe2\x80\x99s 因为 SVG 没有 \xe2\x80\x99t 具有 HTML 的 \xe2\x80\x9c 自动流 \xe2\x80\x9d做。
换句话说,当你有一堆 HTML 元素时,它们会一个接一个地根据盒模型自动布局。
\nSVG 中没有这样的 \xe2\x80\x9cautomatic\xe2\x80\x9d 或 \xe2\x80\x9cdefault\xe2\x80\x9d 布局。因此,SVG 转换默认为从原点计算。(0,0用户坐标中的\xe2\x80\x99s)。
对于大多数元素,\xe2\x80\x99 有一个简单的解决方案:很棒的 CSS 属性transform-box。在大多数情况下,使用以下 CSS 将允许您以与 HTML 元素几乎相同的方式转换 SVG 元素:
/* whatever elements you want to transform */\nrect, polygon { \n transform-box: fill-box; \n transform-origin: center center; /* or `top left`, `center right`, etc. */\n}\n\n.rotate90 {\n transform: rotate(90deg);\n}\nRun Code Online (Sandbox Code Playgroud)\n现在,你可以做类似的事情...
\n<rect class="rotate90" x="123" y="789" width="50" height="50" />\nRun Code Online (Sandbox Code Playgroud)\n并且它会围绕transform-originCSS 中指定的位置旋转。由于上面的示例使用了transform-originof center center,因此它会原地旋转。
这与使用 的 HTML 元素的行为相匹配transform: rotate(\xe2\x80\xa6)。并且 \xe2\x80\x94 尤其是如果 \xe2\x80\x99 在 SVG 图像中存在很多像这样的旋转\xe2\x80\x94,它比等效的 SVG 标记要好得多。
因为SVG\xe2\x80\x99srotate()函数的语法略有不同,因此没有与transform-box: fill-box上面使用的 CSS 等效的语法,除非您为每次旋转指定 X 和 Y 坐标。
这意味着你必须每次都输入旋转点,如下所示:
\n<rect class="rotate90" x="123" y="789" width="50" height="50" />\nRun Code Online (Sandbox Code Playgroud)\n我遇到的问题是CSS 解决方案不适用于<use />元素。
\xe2\x80\x99的原因非常清楚:<use />元素将引用的元素克隆到新位置。因此,就 CSS 而言,它正在转换<use />元素,而不是克隆的 (Shadow-DOM) 内容。
当涉及到将 CSS 应用到<use />\xe2\x80\x94 的其他挑战(例如设置不同的配色方案\xe2\x80\x94)时,有一些解决方案(例如SVG 超级英雄 Sara Soueidan 的解决方案)。
但是当涉及到解决坐标问题时,我还没有找到解决办法。
\n编辑:为了更明确地了解 I\xe2\x80\x99m 的用途,这里有一些示例代码。
\n<rect x="123" y="789" width="50" height="50" \n transform="rotate(90 123 789)"\n></rect>\n<!-- \n In this example, the rotation pivots around the X and Y coordinates of the `rect` element.\n \n If you wanted to rotate around the center, you would have to calculate:\n \n x + width/2\n y + width/2\n\n And use those values in the `rotate()` function instead.\n\n -->\nRun Code Online (Sandbox Code Playgroud)\n.transform-tl,\n.transform-tc,\n.transform-tr,\n.transform-cl,\n.transform-cc,\n.transform-cr,\n.transform-bl,\n.transform-bc,\n.transform-br {\n transform-box: fill-box;\n}\n\n.transform-tl { transform-origin: top left; }\n.transform-tc { transform-origin: top center; }\n/* \n\xe2\x80\xa6and so on, for the other combinations of `transform-origin` keyword values\xe2\x80\xa6 \n*/\n\n.rotate90.cw {\n transform: rotate(90deg)\n}\n\n.rotate90.ccw {\n transform: rotate(-90deg)\n}\nRun Code Online (Sandbox Code Playgroud)\n(感谢 @PaulLeBeau 的推动,包含了这段代码。)
\n有没有人有办法解决吗?
\n(即使是解决方案\xe2\x80\x94,只要它比transform在每个<use />\xe2\x80\x94 上指定 SVG 属性更少的重复,也会受到欢迎!)
假设与@Sphinxxx假设的条件相同......
\n然后,您还可以将元素包装<use>在 group ( <g>) 元素中,并对其应用旋转类。
/* whatever elements you want to transform */\nrect, polygon, use, g {\n transform-box: fill-box;\n transform-origin: center center; /* or `top left`, `center right`, etc. */\n}\n\n.rotate45 {\n transform: rotate(45deg);\n}Run Code Online (Sandbox Code Playgroud)\r\n<svg width="300" height="200">\n <defs>\n <rect id="rr" x="80" y="60" width="50" height="50" />\n </defs>\n\n <use href="#rr" x="100" y="0" fill="tomato" />\n <g class="rotate45">\n <use href="#rr" x="100" y="0" fill="lime" />\n </g>\n</svg>Run Code Online (Sandbox Code Playgroud)\r\n这是怎么回事?为什么这有效?
\n原因与<use>元素如何取消引用以及发生这种情况时发生的转换有关。如果您阅读了SVG 规范中有关元素的部分<use>,它会说:
\n\n在生成的内容中,\xe2\x80\x98use\xe2\x80\x99 将替换为 \xe2\x80\x98g\xe2\x80\x99,其中 \xe2\x80\x98use\xe2\x80 中的所有属性\x99 元素,\xe2\x80\x98x\xe2\x80\x99、\xe2\x80\x98y\xe2\x80\x99、\xe2\x80\x98width\xe2\x80\x99、\xe2\x80\x98height 除外\xe2\x80\x99 和 \xe2\x80\x98xlink:href\xe2\x80\x99 被传输到生成的 \xe2\x80\x98g\xe2\x80\x99 元素。附加变换translate(x,y)被附加到生成的\xe2\x80\x98g\xe2\x80\上的\xe2\x80\x98transform\xe2\x80\x99属性的末尾(即右侧) x99,其中 x 和 y 表示 \xe2\x80\x98use\xe2\x80\ 上的 \xe2\x80\x98x\xe2\x80\x99 和 \xe2\x80\x98y\xe2\x80\x99 属性的值x99 元素。
\n
因此,以下 SVG(我认为这将与您尝试的类似):
\n<use href="#rr" x="100" y="0" fill="lime" class="rotate45" />\nRun Code Online (Sandbox Code Playgroud)\n将被解引用为等价的:
\n<g fill="blue" transform="rotate(45) translate(100,0)">\n <rect x="80" y="60" width="50" height="50" />\n</g>\nRun Code Online (Sandbox Code Playgroud)\n由于您可以将变换视为从右向左应用,因此translate(100,0)将在旋转之前应用变换,这意味着旋转将移动距您想要的位置偏移 100 像素的对象。这就是为什么transform-box: fill-box不适用于<use>元素。
<use href="#rr" x="100" y="0" fill="lime" class="rotate45" />\nRun Code Online (Sandbox Code Playgroud)\r\n<g fill="blue" transform="rotate(45) translate(100,0)">\n <rect x="80" y="60" width="50" height="50" />\n</g>\nRun Code Online (Sandbox Code Playgroud)\r\n然而,根据我的解决方案,<g>+<use>设置...
<g class="rotate45">\n <use href="#rr" x="100" y="0" fill="lime" />\n</g>\nRun Code Online (Sandbox Code Playgroud)\n将被解引用为等价的:
\n<g class="rotate45">\n <g fill="lime" transform="translate(100,0)">\n <rect x="80" y="60" width="50" height="50" />\n </g>\n</g>\nRun Code Online (Sandbox Code Playgroud)\nrect, polygon, use, g {\n transform-box: fill-box;\n transform-origin: center center; /* or `top left`, `center right`, etc. */\n}\n\n.rotate45 {\n transform: rotate(45deg);\n}Run Code Online (Sandbox Code Playgroud)\r\n<svg width="300" height="200">\n <defs>\n <rect id="rr" x="80" y="60" width="50" height="50" />\n </defs>\n\n <use href="#rr" x="100" y="0" fill="tomato" />\n\n <use href="#rr" x="100" y="0" fill="blue" stroke="blue" class="rotate45" />\n\n <g fill="lime" transform="rotate(45) translate(100,0)">\n <rect x="80" y="60" width="50" height="50" />\n </g>\n</svg>Run Code Online (Sandbox Code Playgroud)\r\n在此版本中,两个变换操作分别应用于不同的元素,因此 和transform-box分别transform-origin应用。并且变换原点对翻译没有影响。
所以这意味着transform-box旋转的计算(即在 上<g>)将应用于已经翻译的对象。所以它会按照你想要的方式运行。
在之前的日子里transform-box,这两个例子会给出相同的结果。
| 归档时间: |
|
| 查看次数: |
488 次 |
| 最近记录: |