# 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**

**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`