Programmatically generate SVG (vector) images, animations, and interactive Jupyter widgets
at 2.4.0 8.0 kB view raw
1<!DOCTYPE html> 2<head> 3<meta charset="utf-8"> 4</head> 5<body> 6<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 7 width="400" height="200" viewBox="-200.0 -100.0 400 200" onload="svgOnLoad(event);"> 8<defs> 9</defs> 10<rect x="-200" y="-100" width="400" height="200" fill="#eee" /> 11<circle cx="0" cy="0" r="40" fill="green" /> 12<circle cx="0" cy="0" r="0" fill="gray"> 13<animate attributeName="cx" dur="8s" values="-100;0;100;0;-100" keyTimes="0;0.25;0.5;0.75;1" repeatCount="indefinite" fill="freeze" /> 14<animate attributeName="cy" dur="8s" values="0;-100;0;100;0" keyTimes="0;0.25;0.5;0.75;1" repeatCount="indefinite" fill="freeze" /> 15<animate attributeName="r" dur="8s" values="0;40;0;40;0" keyTimes="0;0.25;0.5;0.75;1" repeatCount="indefinite" fill="freeze" /> 16</circle> 17<rect x="0" y="0" width="0" height="0" fill="silver"> 18<animate attributeName="x" dur="8s" values="-100;-20;100;-20;-100" keyTimes="0;0.25;0.5;0.75;1" repeatCount="indefinite" fill="freeze" /> 19<animate attributeName="y" dur="8s" values="0;-120;0;80;0" keyTimes="0;0.25;0.5;0.75;1" repeatCount="indefinite" fill="freeze" /> 20<animate attributeName="width" dur="8s" values="0;40;0;40;0" keyTimes="0;0.25;0.5;0.75;1" repeatCount="indefinite" fill="freeze" /> 21<animate attributeName="height" dur="8s" values="0;40;0;40;0" keyTimes="0;0.25;0.5;0.75;1" repeatCount="indefinite" fill="freeze" /> 22</rect> 23<text x="0" y="1" font-size="30" fill="yellow" text-anchor="middle" dominant-baseline="central">0<animate attributeName="visibility" dur="8s" values="visible;hidden;hidden" keyTimes="0;0.25;1" repeatCount="indefinite" fill="freeze" /></text> 24<text x="0" y="1" font-size="30" fill="yellow" text-anchor="middle" dominant-baseline="central">1<animate attributeName="visibility" dur="8s" values="hidden;visible;hidden;hidden" keyTimes="0;0.25;0.5;1" repeatCount="indefinite" fill="freeze" /></text> 25<text x="0" y="1" font-size="30" fill="yellow" text-anchor="middle" dominant-baseline="central">2<animate attributeName="visibility" dur="8s" values="hidden;hidden;visible;hidden;hidden" keyTimes="0;0.25;0.5;0.75;1" repeatCount="indefinite" fill="freeze" /></text> 26<text x="0" y="1" font-size="30" fill="yellow" text-anchor="middle" dominant-baseline="central">3<animate attributeName="visibility" dur="8s" values="hidden;hidden;visible;visible" keyTimes="0;0.5;0.75;1" repeatCount="indefinite" fill="freeze" /></text> 27<g id="scrub"> 28<path d="M-168.0,90.0 L168.0,90.0" stroke="#ccc" stroke-width="4" stroke-linecap="round" /> 29<rect x="-168.0" y="90.0" width="0" height="0.001" stroke="#05f" stroke-width="4" stroke-linejoin="round"> 30<animate attributeName="width" dur="8s" values="0;336" keyTimes="0;1" repeatCount="indefinite" fill="freeze" /> 31</rect> 32<g id="scrub-capture" data-xmin="-168.0" data-xmax="168.0" data-totaldur="8" data-startdelay="0" data-enddelay="0" data-pauseonload="0"> 33<rect x="-170.0" y="80.0" width="340" height="20" fill="rgba(255,255,255,0)" /> 34<circle cx="-168.0" cy="90.0" r="6" fill="#05f" id="scrub-knob" visibility="hidden"> 35<animate attributeName="cx" dur="8s" values="-168.0;168.0" keyTimes="0;1" repeatCount="indefinite" fill="freeze" /> 36</circle> 37</g> 38<g id="scrub-play" visibility="hidden"> 39<rect x="-191.0" y="86.0" width="8" height="8" fill="#05f" stroke="#05f" stroke-width="8" stroke-linejoin="round" /> 40<path d="M-191.0,86.0 v8.0 l8.0,-4.0 Z" fill="#eee" /> 41</g> 42<g id="scrub-pause" visibility="hidden"> 43<rect x="-191.0" y="86.0" width="8" height="8" fill="#05f" stroke="#05f" stroke-width="8" stroke-linejoin="round" /> 44<rect x="-190.0" y="86.0" width="2.0" height="8.0" fill="#eee" /> 45<rect x="-186.0" y="86.0" width="2.0" height="8.0" fill="#eee" /> 46</g> 47</g> 48<script>/*<![CDATA[*/ 49/* Animation playback controls generated by drawsvg */ 50/* https://github.com/cduck/drawsvg/ */ 51function svgOnLoad(event) { 52 /* Support standalone SVG or embedded in HTML or iframe */ 53 if (event && event.target && event.target.ownerDocument) { 54 svgSetup(event.target.ownerDocument); 55 } else if (document && document.currentScript 56 && document.currentScript.parentElement) { 57 svgSetup(document.currentScript.parentElement); 58 } 59} 60function svgSetup(doc) { 61 var svgRoot = doc.documentElement || doc; 62 var scrubCapture = doc.getElementById("scrub-capture"); 63 /* Block multiple setups */ 64 if (!scrubCapture || scrubCapture.getAttribute("svgSetupDone")) { 65 return; 66 } 67 scrubCapture.setAttribute("svgSetupDone", true); 68 var scrubContainer = doc.getElementById("scrub"); 69 var scrubPlay = doc.getElementById("scrub-play"); 70 var scrubPause = doc.getElementById("scrub-pause"); 71 var scrubKnob = doc.getElementById("scrub-knob"); 72 var scrubXMin = parseFloat(scrubCapture.dataset.xmin); 73 var scrubXMax = parseFloat(scrubCapture.dataset.xmax); 74 var scrubTotalDur = parseFloat(scrubCapture.dataset.totaldur); 75 var scrubStartDelay = parseFloat(scrubCapture.dataset.startdelay); 76 var scrubEndDelay = parseFloat(scrubCapture.dataset.enddelay); 77 var scrubPauseOnLoad = parseFloat(scrubCapture.dataset.pauseonload); 78 var paused = false; 79 var dragXOffset = 0; 80 var point = svgRoot.createSVGPoint(); 81 82 function screenToSvgX(p) { 83 var matrix = scrubKnob.getScreenCTM().inverse(); 84 point.x = p.x; 85 point.y = p.y; 86 return point.matrixTransform(matrix).x; 87 }; 88 function screenToProgress(p) { 89 var matrix = scrubKnob.getScreenCTM().inverse(); 90 point.x = p.x; 91 point.y = p.y; 92 var x = point.matrixTransform(matrix).x; 93 if (x <= scrubXMin) { 94 return scrubStartDelay / scrubTotalDur; 95 } 96 if (x >= scrubXMax) { 97 return (scrubTotalDur - scrubEndDelay) / scrubTotalDur; 98 } 99 return (scrubStartDelay/scrubTotalDur 100 + (x - dragXOffset - scrubXMin) 101 / (scrubXMax - scrubXMin) 102 * (scrubTotalDur - scrubStartDelay - scrubEndDelay) 103 / scrubTotalDur); 104 }; 105 function currentScrubX() { 106 return scrubKnob.cx.animVal.value; 107 }; 108 function pause() { 109 svgRoot.pauseAnimations(); 110 scrubPlay.setAttribute("visibility", "visible"); 111 scrubPause.setAttribute("visibility", "hidden"); 112 paused = true; 113 }; 114 function play() { 115 svgRoot.unpauseAnimations(); 116 scrubPause.setAttribute("visibility", "visible"); 117 scrubPlay.setAttribute("visibility", "hidden"); 118 paused = false; 119 }; 120 function scrub(playbackFraction) { 121 var t = scrubTotalDur * playbackFraction; 122 /* Stop 10ms before end to avoid loop (>=1ms needed on FF) */ 123 var limit = scrubTotalDur - 10e-3; 124 if (t < 0) t = 0; 125 else if (t > limit) t = limit; 126 svgRoot.setCurrentTime(t); 127 }; 128 function mousedown(e) { 129 svgRoot.pauseAnimations(); 130 if (e.target == scrubKnob) { 131 dragXOffset = screenToSvgX(e) - currentScrubX(); 132 } else { 133 dragXOffset = 0; 134 } 135 scrub(screenToProgress(e)); 136 /* Global document listeners */ 137 document.addEventListener('mousemove', mousemove); 138 document.addEventListener('mouseup', mouseup); 139 e.preventDefault(); 140 }; 141 function mouseup(e) { 142 dragXOffset = 0; 143 document.removeEventListener('mousemove', mousemove); 144 document.removeEventListener('mouseup', mouseup); 145 if (!paused) { 146 svgRoot.unpauseAnimations(); 147 } 148 e.preventDefault(); 149 }; 150 function mousemove(e) { 151 scrub(screenToProgress(e)); 152 }; 153 scrubPause.addEventListener("click", pause); 154 scrubPlay.addEventListener("click", play); 155 scrubCapture.addEventListener("mousedown", mousedown); 156 scrubContainer.setAttribute("visibility", "visible"); 157 scrubKnob.setAttribute("visibility", "visible"); 158 if (scrubPauseOnLoad) { 159 pause(); 160 scrub(0); 161 } else { 162 play(); 163 } 164}; 165svgOnLoad(); 166/*]]>*/</script> 167</svg> 168</body> 169</html>