SVG Dataflow JS
by balefrost
HTML
<svg id="without-dirty" width="200" height="300">
<defs>
<marker id="arrow" viewBox="-5 -10 20 20" orient="auto">
<polygon points="-5,-10 15,0 -5,10 0,0" />
</marker>
<clipPath id="node" clipPathUnits="objectBoundingBox">
<circle cx="0.5" cy="0.5" r="0.5" />
</clipPath>
</defs>
<line x1="100" y1="0" x2="100" y2="43.75" marker-end="url(#arrow)" stroke="black" stroke-width="5" />
<line x1="100" y1="75" x2="67.334" y2="123.998" marker-end="url(#arrow)" stroke="black" stroke-width="5" />
<line x1="100" y1="75" x2="132.666" y2="123.998" marker-end="url(#arrow)" stroke="black" stroke-width="5" />
<line x1="50" y1="150" x2="82.666" y2="198.998" marker-end="url(#arrow)" stroke="black" stroke-width="5" />
<line x1="150" y1="150" x2="117.334" y2="198.998" marker-end="url(#arrow)" stroke="black" stroke-width="5" />
<line x1="100" y1="225" x2="100" y2="288.75" marker-end="url(#arrow)" stroke="black" stroke-width="5" />
<g clip-path="url(#node)" transform="translate(100,-15)">
<rect x="-10" y="-10" width="20" height="20" fill="red" />
<rect x="0" y="-10" width="10" height="20" fill="red"></rect>
<animateTransform id="withoutDirtyStart" begin="withoutDirty.click" dur="0.5s" attributeName="transform" type="translate" from="100,-15" to="100,75" fill="freeze" />
<animateTransform begin="withoutDirtyStart.begin+0.5s" dur="0.5s" attributeName="transform" type="translate" from="100,75" to="150,150" fill="freeze" />
<animateTransform begin="withoutDirtyStart.begin+1s" dur="0.5s" attributeName="transform" type="translate" from="150,150" to="100,225" fill="freeze" />
<animateTransform begin="withoutDirtyStart.begin+1.5s" dur="0.5s" attributeName="transform" type="translate" from="100,225" to="100,315" fill="freeze" />
<animateTransform begin="withoutDirtyStart.begin+2.5s" dur="0.5s" attributeName="transform" type="translate" from="100,75" to="50,150" fill="freeze" />
<animateTransform...
JavaScript
(function() {
var svg = document.querySelector('#without-dirty');
var svgns = "http://www.w3.org/2000/svg";
function createTransitionable() {
var rect = document.createElementNS(svgns, 'rect');
rect.setAttribute('fill', 'green');
var toRed = document.createElementNS(svgns, 'animate');
toRed.setAttribute('begin', 'indeterminite');
toRed.setAttribute('attributeName', 'fill');
toRed.setAttribute('dur', '0.2s');
toRed.setAttribute('from', 'green');
toRed.setAttribute('to', 'red');
toRed.setAttribute('fill', 'freeze');
rect.appendChild(toRed);
var toGreen = document.createElementNS(svgns, 'animate');
toGreen.setAttribute('begin', 'indeterminite');
toGreen.setAttribute('attributeName', 'fill');
toGreen.setAttribute('dur', '0.2s');
toGreen.setAttribute('from', 'red');
toGreen.setAttribute('to', 'green');
toGreen.setAttribute('fill', 'freeze');
rect.appendChild(toGreen);
return {
element: rect,
goRed: function() { toRed.beginElement(); },
goGreen: function() { toGreen.beginElement(); }
};
}
function createNode(x, y) {
var g = document.createElementNS(svgns, 'g');
g.setAttribute('clip-path', 'url(#node)');
g.setAttribute('transform', 'translate(' + x + ',' + y + ')');
var rect = createTransitionable();
rect.element.setAttribute('x', -20);
rect.element.setAttribute('y', -20);
rect.element.setAttribute('width', 40);
rect.element.setAttribute('height', 40);
g.appendChild(rect.element);
return {
element: g,
goRed: function() { rect.goRed(); },
goGreen: function() { rect.goGreen(); }
};
}
function createSplitNode(x, y, r) {
var g = document.createElementNS(svgns, 'g');
g.setAttribute('clip-path',...