Skip to content

Instantly share code, notes, and snippets.

@petekneller
Last active April 17, 2018 21:58
Show Gist options
  • Save petekneller/559358245e594391bc3edf9fb8bd5b16 to your computer and use it in GitHub Desktop.
Save petekneller/559358245e594391bc3edf9fb8bd5b16 to your computer and use it in GitHub Desktop.
SVG schematics
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Some experiments in how I might do multipart diagrams/schematics with SVG</title>
</head>
<body>
<h1>The problem</h1>
<p>I have a need/want to knock up schematic-like diagrams on the web with which I can: display either the whole or only parts of the diagram; zoom/scale or transform the part(s) being displayed. SVG seems to make sense a basis for this, so the question becomes one of: how do I do this with SVG?</p>
<h1>Solution 1: create reusable pieces of diagram which are then pulled together at the use site</h1>
<p>Say we have the following sub-assemblies:</p>
<svg xmlns="http://www.w3.org/2000/svg" height="0" width="0">
<defs>
<circle id="aCircle" r="30" cx="30" cy="30" stroke="black" fill="yellow"/>
<rect id="aRect" width="120" height="10" stroke="black" fill="black" />
<g id="sa1">
<use href="#aCircle" />
<use href="#aCircle" transform="translate(100, 0)" />
<use href="#aRect" transform="translate(20, 25)" />
</g>
<g id="sa2">
<use href="#aRect" transform="translate(60, 60) rotate(45) translate(-60, -5)" />
<use href="#aRect" transform="translate(60, 60) rotate(-45) translate(-60, -5)" />
</g>
</defs>
</svg>
<svg xmlns="http://www.w3.org/2000/svg">
<use href="#sa1" />
<text x="40" y="80">Sub-assembly 1</text>
</svg>
<svg xmlns="http://www.w3.org/2000/svg">
<use href="#sa2" />
<text x="20" y="130">Sub-assembly 2</text>
</svg>
<p>As long as each of those are defined in a &lt;def&gt; block and given a unique id then each sub-assembly can be &lt;use&gt;'d independently in different scenarios. They can be rendered and manipulated alone, or they can be pulled together, like so:</p>
<svg xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0,30)">
<use href="#sa1" />
<use href="#sa2" transform="translate(20, -30)"/>
<text x="30" y="100">Whole assembly</text>
</g>
</svg>
<p>And of course each sub-assembly could be composed of further sub-assemblies which are composed of ... and so on to whatever level of detail is useful. However because the arranging of sub-assemblies is done at the use site I suspect that if there are a large number of <i>combinations</i> of different sub-assemblies then this will get tiresome. For example imagine you have sub-assemblies A, B and C. If you want to render A and B together you &lt;use&gt; them in the same diagram transforming as appropriate. Now if you want a diagram of A and C then you repeat the process, also transforming as appropriate. Now what if you want to render B and C together? There's already some A-specific transformation necessary in the first example (A + B) we've just built. And some C-specific transformation in the second example (A + C). But those must be repeated for the third, making this method very not DRY.</p>
<h1>Solution 2: Define a single diagram but show/hide independent sections with styling</h1>
<svg xmlns="http://www.w3.org/2000/svg" height="0" width="0">
<defs>
<g id="wa" transform="translate(0,30)">
<g style="visibility:var(--sa1-vis, hidden)">
<use href="#aCircle" />
<use href="#aCircle" transform="translate(100, 0)" />
<use href="#aRect" transform="translate(20, 25)" />
</g>
<g transform="translate(20, -30)" style="visibility:var(--sa2-vis, hidden)">
<use href="#aRect" transform="translate(60, 60) rotate(45) translate(-60, -5)" />
<use href="#aRect" transform="translate(60, 60) rotate(-45) translate(-60, -5)" />
</g>
</g>
</defs>
</svg>
<p>An alternative is to define the whole diagram in one go (in a &lt;defs&gt;) but group each sub-assembly within its own &lt;g&gt;. Each sub-assembly can then be given a CSS visibility property based on a variable. At the use-site the diagram has only to be &lt;use&gt;'d as a single unit, transforming as needed. The visiblility of its sub-assemblies can be toggled on/off by setting an appropriate value for each of the CSS variales governing the individual sub-assemblies. For example, each of the below diagrams is a single &lt;use&gt; introducing the whole diagram but setting a different value for the variable <i>saX-vis</i>, where X is the sub-assembly.</p>
<svg xmlns="http://www.w3.org/2000/svg">
<use href="#wa" style="--sa1-vis:visible, --sa2-vis:hidden" />
<text x="30" y="130">style="--sa1-vis:visible, --sa2-vis:hidden"</text>
</svg>
<svg xmlns="http://www.w3.org/2000/svg">
<use href="#wa" style="--sa1-vis:hidden; --sa2-vis:visible" />
<text x="30" y="130">style="--sa1-vis:hidden; --sa2-vis:visible"</text>
</svg>
<svg xmlns="http://www.w3.org/2000/svg">
<use href="#wa" style="--sa1-vis:visible; --sa2-vis:visible" />
<text x="30" y="130">style="--sa1-vis:visible; --sa2-vis:visible"</text>
</svg>
<p>Or set a default value for the visibility variale and leave it off the use-site. Eg. on sub-assembly 1 is: <i>style="visibility:var(--sa1-vis, hidden)"</i> so the sub-assembly 2 diagram can become:</p>
<svg xmlns="http://www.w3.org/2000/svg">
<use href="#wa" style="--sa2-vis:visible" />
<text x="30" y="130">style="--sa2-vis:visible"</text>
</svg>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment