Say I have a rectangle with a complex transformation:
<rect width="1000" height="1000"
transform="rotate(-30) skewX(30) scale(1, 0.86062)" />
Would it be possible to store the transformation so that if I'm creating another element with the same transformation I don't have to repeat it? Something like:
<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>
Note: I put the objects into groups because I want to combine the complex transformation with others so the solution at How to define a transform in the <defs>? won't work.
Thanks to the marked answer I was able to do magical isomorphic projections with readable code. It may have some limitations, but kind of useful.
<?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>
This is another approach using DTD.
But I don't know xml parser of java supports DTD or not...
<?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>