使用def在SVG中重用转换

时间:2014-08-06 10:47:44

标签: 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>

2 个答案:

答案 0 :(得分:1)

尝试css转换,但我不知道这个代码在android上运行良好 http://jsfiddle.net/defghi1977/f7nocht4/

<?xml version="1.0" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
    <style><![CDATA[
.transform{
    transform:rotate(10deg);
}
    ]]></style>
    <g transform="translate(10,10)">
        <rect x="10" y="10" width="80" height="80" class="transform"/>
    </g>
    <g transform="translate(100,10)">
        <ellipse cx="50" cy="50" rx="40" ry="30" class="transform"/>
    </g>
</svg>

答案 1 :(得分:1)

这是使用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>