---
# System prepended metadata

title: 【Day14】SVG應用

---

# 【Day14】SVG應用
## SVG是甚麼
SVG為==可縮放的向量圖形==

在縮放時，它的像素都不會變，也就是說，放多大都會很清楚；
而一般的圖片為點陣圖，放大時會變得模糊。

## SVG常用元素與其屬性
- line 直線
x1,y1,x2,y2 (起點,終點)
- rect 矩形
x,y,w,h (起點,寬高)
- circle 圓圈
cx,cy,r (起點,終點,半徑)
- ellipse 橢圓
cx,cy,rx,ry 
- polyline 折線
points="x,y;x,y" 

## 繪製向量圖片
### 座標概念圖
![](https://hackmd.io/_uploads/BkKmDGsTh.png)
*圖片來源: https://developer.mozilla.org/zh-TW/docs/Web/SVG/Tutorial/Positions/canvas_default_grid.png*
### 實際簡易演練---圓圈

問題：為何只出現一小部分的圓呢
![](https://hackmd.io/_uploads/SyjVYfiT2.png)

答：因為觀景窗預設起點為(0,0)
![](https://hackmd.io/_uploads/S1ahKfiT2.png)
*圖片來源：https://hahow.in/courses/56189df9df7b3d0b005c6639/discussions?item=5a1e1745a2c4b000589dd22c*

解決方法：
改變觀景窗起點位置。(如下圖)
![](https://hackmd.io/_uploads/HkdDcGjpn.png)

## CSS/SVG比較表格
SVG屬性值與CSS不同
![](https://hackmd.io/_uploads/SJHwhzjan.png)
*圖片來源：https://hahow.in/courses/56189df9df7b3d0b005c6639/discussions?item=5a1e1745a2c4b000589dd22c*

## 初階繪製SVG參考範例
**程式碼**
HTML(jade)
```htmlmixed=
svg#pic1(viewbox="-50 -50 100 100")
  line(x1=-20 y1=0 x2=20 y2=0)
  line(x1=-0 y1=-20 x2=0 y2=20)
  circle(cx=0 cy=0 r=10)
  
svg#pic2(viewbox="-50 -50 100 100")
  circle(cx=0 cy=0 r=10)
  line(x1=-20 y1=0 x2=20 y2=0)
  line(x1=-0 y1=-20 x2=0 y2=20)
  rect(x=-20 y=-20 width=40 height=40)
  
svg#pic3(viewbox="0 0 200 200")
  circle(cx=0 cy=50 r=3)
  circle(cx=50 cy=80 r=3)
  circle(cx=100 cy=60 r=3)
  circle(cx=150 cy=20 r=3)
  circle(cx=200 cy=40 r=3)
  polyline(points="0,50 50,80 100,60 150,20 200,40")
  
svg#pic4(viewbox="0 0 200 200")
  rect(x=0 y=0 width=20 height=100)
  rect(x=30 y=0 width=20 height=120)
  rect(x=60 y=0 width=20 height=140)
  rect(x=90 y=0 width=20 height=160)
  rect(x=120 y=0 width=20 height=120)
  rect(x=150 y=0 width=20 height=80)
  rect(x=180 y=0 width=20 height=60)
  
svg#pic5(viewbox="-50 -40 100 100")
  rect(x=-30 y=-20 width=60 height=40)
  rect(x=-25 y=-15 width=50 height=30)
  rect(x=-2 y=20 width=4 height=10)
  rect(x=-10 y=30 width=20 height=5)
  line(x1=-20 y1=0 x2=-8 y2=0)
  line(x1=-20 y1=5 x2=-5 y2=5)
  circle(cx=10 cy=0 r=7 )
  text(x=-30 y=50) My computer
```
CSS(sass)
```css=
svg
  width: 240px
  border: solid 2px
 
#pic1
  stroke: black
  stroke-width: 3px
  & circle
    fill: white
#pic2
  stroke: black
  stroke-width: 2px
  & circle
    fill: white
  & rect
    fill: none
    
#pic3
  stroke: black
  stroke-width: 2px
  & polyline
    fill: none
    
#pic5
  stroke: black
  stroke-width: 2px
  fill: none
  & circle
    fill: red
    stroke: none
  & text
    fill: black
    stroke: none
    font-family: 微軟正黑體
    font-size: 10px
```
**呈現**
![](https://hackmd.io/_uploads/SkB-IXsp2.png)

## 讓圖像動起來！
製作SVG動畫大致上可分為三種方式：
1. 針對**屬性**值做動畫
animate(attributeName="屬性x/y/width..." dur="長度" values="影格" repeatCount="次數")
:::info
優點：動畫直接寫在HTML裡，不需要在CSS做調整即完成。
缺點：能設定的東西較少，例如：速度曲線調整。
:::

2. 針對**變形/位移**做動畫
animateTransform(attributeName="transform" type="屬性scale/rotate" dur="長度" values="影格" repeatCount="次數")
:::info
優點：動畫直接寫在HTML裡，不需要在CSS做調整即完成。
缺點：能設定的東西較少，例如：速度曲線調整，在定義一些影格時可能較為麻煩。
:::

3. 使用**CSS**做動畫
transform: translateX/translateY/scale/rotate...(與之前同)
transition-duration: 時長
transition-origin: x位置 y位置 (e.g. center bottom /100% 0%)
animation/keyframes...
:::info
優點：動畫直接寫在HTML裡，不需要在CSS做調整即完成。
缺點：能設定的東西較少，例如：速度曲線調整。
:::

## 進階繪製SVG參考範例---讓圖片動起來
**程式碼**
HTML(jade)
```htmlmixed=
svg#pic1(viewbox="-50 -50 100 100")
  line(x1=-20 y1=0 x2=20 y2=0)
  line(x1=-0 y1=-20 x2=0 y2=20)
  circle(cx=0 cy=0 r=10)
    animate(attributeName="r" dur="2s" values="10;20;10" repeatCount="indefinite")
  
svg#pic2(viewbox="-50 -50 100 100")
  circle(cx=0 cy=0 r=10)
  g
    line(x1=-20 y1=0 x2=20 y2=0)
    line(x1=-0 y1=-20 x2=0 y2=20)
    rect(x=-20 y=-20 width=40 height=40)
    animateTransform(attributeName="transform" type="rotate" dur="2s" values="0;360" repeatCount="indefinite")
  
svg#pic3(viewbox="0 0 200 200")
  circle(cx=0 cy=50 r=3)
    animate(attributeName="cy" dur="2s" values="50;60;50" repeatCount="indefinite")
  circle(cx=50 cy=80 r=3)
    animate(attributeName="cy" dur="2s" values="80;40;80" repeatCount="indefinite")
  circle(cx=100 cy=60 r=3)
    animate(attributeName="cy" dur="2s" values="60;30;60" repeatCount="indefinite")
  circle(cx=150 cy=20 r=3)
    animate(attributeName="cy" dur="2s" values="20;70;20" repeatCount="indefinite")
  circle(cx=200 cy=40 r=3)
    animate(attributeName="cy" dur="2s" values="40;60;40" repeatCount="indefinite")
  polyline(points="0,50 50,80 100,60 150,20 200,40")
    animate(attributeName="points" dur="2s" values="0,50 50,80 100,60 150,20 200,40;0,60 50,40 100,30 150,70 200,60;0,50 50,80 100,60 150,20 200,40" repeatCount="indefinite")
  
svg#pic4(viewbox="0 0 200 200")
  rect(x=0 y=0 width=20 height=100)
    animate(attributeName="height" begin="0s" dur="2s" values="100;200;100" repeatCount="indefinite")
  rect(x=30 y=0 width=20 height=120)
    animate(attributeName="height" begin="-0.3s" dur="2s" values="100;200;100" repeatCount="indefinite")
  rect(x=60 y=0 width=20 height=140)
    animate(attributeName="height" begin="-0.6s" dur="2s" values="100;200;100" repeatCount="indefinite")
  rect(x=90 y=0 width=20 height=160)
    animate(attributeName="height" begin="-0.9s" dur="2s" values="100;200;100" repeatCount="indefinite")
  rect(x=120 y=0 width=20 height=120)
    animate(attributeName="height" begin="-1.2s" dur="2s" values="100;200;100" repeatCount="indefinite")
  rect(x=150 y=0 width=20 height=80)
    animate(attributeName="height" begin="-1.5s" dur="2s" values="100;200;100" repeatCount="indefinite")
  rect(x=180 y=0 width=20 height=60)
    animate(attributeName="height" begin="0s" dur="2s" values="100;200;100" repeatCount="indefinite")
  
svg#pic5(viewbox="-50 -40 100 100")
  rect.frame_outer(x=-30 y=-20 width=60 height=40)
  rect.frame_inner(x=-25 y=-15 width=50 height=30)
  rect.neck(x=-2 y=20 width=4 height=10)
  rect.bottom(x=-10 y=30 width=20 height=5)
  g.screen_content
    line(x1=-20 y1=0 x2=-8 y2=0)
    line(x1=-20 y1=5 x2=-5 y2=5)
    circle(cx=10 cy=0 r=7 )
  text.text(x=-30 y=50) My computer
```
CSS(sass)
```css=
svg
  width: 240px
  border: solid 2px
 
#pic1
  stroke: black
  stroke-width: 3px
  & circle
    fill: white
#pic2
  stroke: black
  stroke-width: 2px
  & circle
    fill: white
  & rect
    fill: none
    
#pic3
  stroke: black
  stroke-width: 2px
  & polyline
    fill: none
    
#pic5
  stroke: black
  stroke-width: 2px
  fill: none
  & circle
    fill: red
    stroke: none
  & text
    fill: black
    stroke: none
    font-family: 微軟正黑體
    font-size: 10px
    
  .frame_outer, .frame_inner, .neck, .bottom
    transform: scale(0)
    transform-origin: left center
    
    transition-duration: 0.5s
    transition-delay: 0.5s
  .screen_content
    opacity: 0
    transition-duration: 0.5s
    transition-delay: 0s
    
  &:hover
    .frame_outer, .frame_inner, .neck, .bottom
      transform: scale(1)
      transition-delay: 0.5s
    .neck, .bottom
      transition-delay: 0s
    .screen_content
      opacity: 1
      transition-delay: 1s
```
**呈現**
{%youtube zHoTdat4ozc %}

:::warning
內容主要整理自「動畫互動網頁程式入門 (HTML/CSS/JS)」課程，網址：https://hahow.in/courses/56189df9df7b3d0b005c6639/discussions?item=5a1e1745a2c4b000589dd21d
:::