svg - 使用 def 在 SVG 中重新使用转换

标签 svg transformation code-reuse

假设我有一个具有复杂变换的矩形:

<rect width="1000" height="1000"
    transform="rotate(-30) skewX(30) scale(1, 0.86062)" />

是否可以存储转换,以便在我使用相同转换创建另一个元素时不必重复它?像这样的东西:

<defs>
    <transform id="complex">rotate(-30) skewX(30) scale(1, 0.86062)</transform>
</defs>
<g transform="translate(100,0) scale(2,1)">
   <rect width="1000" height="1000" transform="#complex" />
    ...
</g>
<g transform="translate(-200,100) rotate(40)"> 
   <circle cx="500" cy="500" r="500" transform="#complex" />
   ...
</g>

注意:我将对象分组,因为我想将复杂的转换与其他转换结合起来,因此解决方案为 How to define a transform in the <defs>?行不通。


更新(回复:解决方案)

感谢标记的答案,我能够使用可读的代码进行神奇的同构投影。它可能有一些限制,但很有用。

<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
    <!--
        Coordinate system
        red  ; -X: left, +X: right, rect facing: right
        green; -Y: back, +Y: front, rect facing: left
        blue ; -Z: down, +Z: up   , rect facing: up
    -->
    <!ENTITY isoAngle "30">
    <!ENTITY isoCos "0.8660254037844386467">
    <!ENTITY sqrt2 "1.41421356237">
    <!ENTITY sqrt2Inv "0.70710678118">
    <!ENTITY isoYZ "rotate(-&isoAngle;) skewX(-&isoAngle;) scale(1, &isoCos;)"><!-- isoX: right facing plane -->
    <!ENTITY isoXZ "rotate(+&isoAngle;) skewX(+&isoAngle;) scale(1, &isoCos;)"><!-- isoY: left facing plane -->
    <!ENTITY isoXY "rotate(-&isoAngle;) skewX(+&isoAngle;) scale(1, &isoCos;)"><!-- isoZ: up facing plane -->
    <!-- isoXY projected Y transform by 350: transform="&isoXY &isoZPreY; translate(+350) &isoZPostY;" -->
    <!ENTITY isoXPreX "rotate( +45) scale(&sqrt2;, 1)"><!ENTITY isoXPostX "scale(&sqrt2Inv;, 1) rotate( -45)">
    <!ENTITY isoXPreY "rotate(+180)"><!ENTITY isoXPostY "rotate(-180)">
    <!ENTITY isoXPreZ "rotate(+270)"><!ENTITY isoXPostZ "rotate(-270)">
    <!ENTITY isoYPreX "rotate(  +0)"><!ENTITY isoYPostX "rotate(  -0)">
    <!ENTITY isoYPreY "rotate(+135) scale(&sqrt2;, 1)"><!ENTITY isoYPostY "scale(&sqrt2Inv;, 1) rotate(-135)">
    <!ENTITY isoYPreZ "rotate(+270)"><!ENTITY isoYPostZ "rotate(-270)">
    <!ENTITY isoZPreX "rotate( +90)"><!ENTITY isoZPostX "rotate( -90)">
    <!ENTITY isoZPreY "rotate(+180)"><!ENTITY isoZPostY "rotate(-180)">
    <!ENTITY isoZPreZ "rotate(+315) scale(&sqrt2;, 1)"><!ENTITY isoZPostZ "scale(&sqrt2Inv;, 1) rotate(-315)">
]>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-185,-80 460 215"
        xmlns:xlink="http://www.w3.org/1999/xlink">
    <defs>
        <style type="text/css"><![CDATA[
            .up, .left, .right { opacity: .4; }
            .TZ, .TX, .TY { stroke-width: 5; }
            .box { opacity: 1; stroke: black; stroke-width: 1; }
            .right { fill: #f00; }
            .left  { fill: #0f0; }
            .up    { fill: #00f; }
            .TX { stroke: #800; }
            .TY { stroke: #080;}
            .TZ { stroke: #008; }
        ]]></style>
        <rect id="rect" width="50" height="50" rx="5" ry="5" />
    </defs>
    <g transform="translate(-135)">
        <use xlink:href="#rect" class="right"    transform="&isoYZ; &isoXPreX; translate(  0) &isoXPostX;" />
        <use xlink:href="#rect" class="right TX" transform="&isoYZ; &isoXPreX; translate( 50) &isoXPostX;" />
        <use xlink:href="#rect" class="right TY" transform="&isoYZ; &isoXPreY; translate( 50) &isoXPostY;" />
        <use xlink:href="#rect" class="right TZ" transform="&isoYZ; &isoXPreZ; translate( 50) &isoXPostZ;" />
    </g>
    <g transform="translate(0)">
        <use xlink:href="#rect" class="up"    transform="&isoXY; &isoZPreX; translate(  0) &isoZPostX;" />
        <use xlink:href="#rect" class="up TX" transform="&isoXY; &isoZPreX; translate( 50) &isoZPostX;" />
        <use xlink:href="#rect" class="up TY" transform="&isoXY; &isoZPreY; translate( 50) &isoZPostY;" />
        <use xlink:href="#rect" class="up TZ" transform="&isoXY; &isoZPreZ; translate( 50) &isoZPostZ;" />
    </g>
    <g transform="translate(180) translate(0, -25)">
        <use xlink:href="#rect" class="left"    transform="&isoXZ; &isoYPreX; translate(  0) &isoYPostX;" />
        <use xlink:href="#rect" class="left TX" transform="&isoXZ; &isoYPreX; translate( 50) &isoYPostX;" />
        <use xlink:href="#rect" class="left TY" transform="&isoXZ; &isoYPreY; translate( 50) &isoYPostY;" />
        <use xlink:href="#rect" class="left TZ" transform="&isoXZ; &isoYPreZ; translate( 50) &isoYPostZ;" />
    </g>
    <g id="box" transform="translate(0, 60)">
        <use xlink:href="#rect" class="left box" transform="&isoXZ;" />
        <use xlink:href="#rect" class="up box" transform="&isoXY;" />
        <use xlink:href="#rect" class="right box" transform="&isoYZ; &isoXPreX; translate(  50) &isoXPostX;" />
    </g>
</svg>

最佳答案

这是使用 DTD 的另一种方法。
但我不知道java的xml解析器是否支持DTD...

<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
    <!ENTITY transform "rotate(45)">
]>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
    <g transform="translate(10,10)">
        <rect x="10" y="10" width="80" height="80" transform="&transform;"/>
    </g>
    <g transform="translate(100,10)">
        <ellipse cx="50" cy="50" rx="40" ry="30" transform="&transform;"/>
    </g>
</svg>

关于svg - 使用 def 在 SVG 中重新使用转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25158403/

相关文章:

python - 如何渲染 svg 文件的*部分*?

html - HTTP 304 通过 jQuery.html() 加载 SVG

python - 将 Pandas 数据框列和索引转换为值

php - 你知道什么好的数据库模式迁移工具吗?

ios - 使用 GPUImageTransformFilter 和 iOS 平移手势转换 GPUImage 位置?

javascript - 累积填充svg并进行后续计算

html - SVG 对象从外部 CSS 更改颜色

iphone - 适用于 iOS 和 OS X 应用程序的库?

java - 使用泛型的可重用接口(interface)

gradle - 如何在 gradle build 中定义可重用的 block