# SVG Note {%hackmd @RintarouTW/About %} SVG Editor https://editor.method.ac/ - [x] Event - [x] Morphing - [x] Path - [x] Along Path - [x] Filter - [x] Embed $\LaTeX$ - [x] Mask - [x] Clipping - [ ] Pattern ## DOM ### Header ```javascript! <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 100" style="background-color:#111"> </svg> ``` ### Defs Definitions of the resources that could be "reused". ```javascript! <defs> ... </defs> ``` #### Style almost the same with CSS. ```css! <style> ... </style> ``` ##### Animation(Keyframes) ```css! @keyframes animation_name { from { ... } to { ... } } ``` **Example** Rotate360 ```css! @keyframes rotate360 { to { transform: rotate(-360deg); } } ``` #### Element - `<line x1 y1 x2 y2 />` - `<circle x y r />` - g(group) - `<polygon points= .../>` - `<path d=path commands />` path commands: - M: move(x y) - H: line to horizontally (dx) - V: line to vertically (dy) - C: curve to (x1 y1 x2 y2 x y) - Q: curve to (x1 y1 x y) - marker - marker-start - marker-mid - marker-end #### Filter **Gaussian Blur** ```javascript! <filter id="blurMe"> <feGaussianBlur in="SourceGraphic" stdDeviation="1" /> <rect filter="url(#blurMe)"> </filter> ``` **Custom Shadow** ```javascript! <filter id="dropShadow"> <feGaussianBlur in="SourceAlpha" stdDeviation="3" /> <feOffset dx="2" dy="4" /> <feMerge> <feMergeNode /> <feMergeNode in="SourceGraphic" /> </feMerge> </filter> <circle cx="60" cy="60" r="50" fill="green" filter="url(#dropShadow)" /> ``` - [feDropShadow](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feDropShadow) **Lightings** - [feDiffuseLighting](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feDiffuseLighting) - [feDistantLight](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feDistantLight) - [feSpotLight](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feSpotLight) - [fePointLight](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/fePointLight) - [feSpecularLighting](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feSpecularLighting) ### Use x, y is the origin(anchor point) of the referenced element(#id), so the referenced elements could be defined in their own local coodinate space. ```javascript! <use x="50%" y="50%" href="#id" /> ``` ## Tips ### SVG Background Color ```javascript! <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 100" style="background-color:#111"> ``` ### Coordinate System (0, 0) is the top-left of the svg by default. #### ViewBox Define the view port rect. ### Transformation - translate() - scale() - rotate() ### Basic Animation - Animation with @keyframes (CSS animation) - `<animate>` - `<animateColor>` - `<animateTransform>` - `<animateMotion>` **calcMode** = discrete | linear | paced | spline **values** **keyTimes** **keySplines** ![](https://i.imgur.com/xmXS6Y9.png) **from** **to** **by** ### Shape Morphing https://css-tricks.com/svg-shape-morphing-works/ ```javascript! <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 100" style="background-color:#111"> <polygon fill="#0f0" points="0 0, 10 0, 10 10, 0 10"> <animate attributeName="points" begin="0s" dur="1s" to="20 20, 30 20, 40 30, 50 50" repeatCount="indefinite" /> </polygon> </svg> ``` ### Path https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths | command | function | parameters | |:------- |:------------------ |:------------------------------------- | | M(m) | Move to | (d)x, (d)y | | L(l) | Line to | (d)x, (d)y | | H(h) | Horizontal line to | (d)x | | V(v) | Veritical line to | (d)y | | A(a) | Arc to | rx ry radius (d)x (d)y | | C(c) | Bezier Curve to | (d)cx1 (d)cy1 (d)cx2 (d)cy2 (d)x (d)y | | S(s) | Bezier Curve to | (d)cx2 (d)cy2 (d)x (d)y | | Q(q) | Bezier Curve to | (d)cx (d)cy (d)x (d)y | | T(t) | Bezier Curve to | (d)x (d)y | | Z/z | Close Path | | ### animateMotion Animate along path. Reuse path via mpath. ```javascript! <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 100" style="background-color:#111"> <defs> <path id="myPath" d="M150 50 H100 V40 H150 V50 z" /> <rect id="box1" x="0" y="0" width="10" height="10" fill="#0f0" opacity="70%"> <animateMotion id="first" dur="1s" begin="0s;second.end"> <mpath href="#myPath" /> </animateMotion> </rect> <rect id="box2" x="0" y="0" width="10" height="10" fill="#ff0" opacity="70%"> <animateMotion id="second" dur="1s" begin="first.end"> <mpath href="#myPath" /> </animateMotion> </rect> </defs> <use x="0" y="0" href="#box1" /> <use x="0" y="0" href="#box2" /> </svg> ``` ### Clipping and Masking https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Clipping_and_masking **Clipping the element with a clipPath.** ```javascript! <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <defs> <clipPath id="cut-off-bottom"> <rect x="0" y="0" width="200" height="100" /> </clipPath> </defs> <circle cx="100" cy="100" r="100" clip-path="url(#cut-off-bottom)" /> </svg> ``` **Alpha Masking** ```javascript! <svg width="200" height="200" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <defs> <linearGradient id="Gradient"> <stop offset="0" stop-color="black" /> <stop offset="1" stop-color="white" /> </linearGradient> <mask id="Mask"> <rect x="0" y="0" width="200" height="200" fill="url(#Gradient)" /> </mask> </defs> <rect x="0" y="0" width="200" height="200" fill="green" /> <rect x="0" y="0" width="200" height="200" fill="red" mask="url(#Mask)" /> </svg> ``` The color component of the gradient is used as the alpha mask. ## Event Event can't work when `svg` is emebed by `<img>` tag. Only `<svg>` tag in raw html would be parsed by the DOM. ### Begin Animate by SVG itself ```javascript! <polygon id="shape" points=" ... shape 1 points ... "> <animate begin="shape.click" attributeName="points" dur="500ms" to=" ... shape 2 points ... /> </polygon> ``` **Animate Chain** ```javascript! <rect width="10" height="10" x="30" y="10" fill="#00f"> <animate id="third" attributeName="x" to="40" begin="second.end" dur="1s" /> </rect> <rect width="10" height="10" x="20" y="10" fill="#0f0"> <animate id="second" attributeName="x" to="30" begin="first.end" dur="1s" /> </rect> <rect width="10" height="10" x="10" y="10" fill="#f00"> <animate id="first" attributeName="x" to="20" begin="0s;third.end" dur="1s" /> </rect> ``` ### Begin Animate by JavaScript **SVG** ```javascript! <animate id="animation-to-check" begin="indefinite" ... /> ``` **Javascript** ```javascript! <html> <body> <svg width="300" height="120" viewBox="0 0 300 120" xmlns="http://www.w3.org/2000/svg"> <text x="10" y="20">JavaScript Animation Trigger Test</text> <!-- animated rectangle --> <rect id="box" x="10" y="35" height="15" width="0" class="test"> <animate id="ani" attributeName="width" from="0" to="100" begin="startButton.click" dur="8s" fill="freeze" /> </rect> </svg> <script> let ani = document.getElementById('ani') ani.beginElement() </script> </body> </html> ``` ## SVG + $\LaTeX$ ```javascript! <html> <head> <script type="text/javascript" id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js"> </script> </head> <body> <svg viewBox="0 0 300 200"> <foreignObject width="200" height="110" x="10" y="10" transform="translate(200 0) scale(0.3 0.3)"> <text> \( \pmatrix{x\\y}\implies\pmatrix{-y\\x} \) </text> <text> \( \pmatrix{x\\y}\implies\pmatrix{y\\x}\implies\pmatrix{-y\\x} \) </text> </foreignObject> </svg> </body> </html> ``` ## References - https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute ###### tags: `svg`