「SVG動畫進階使用」修訂間的差異
行 267: | 行 267: | ||
*以此類推,雖然曲線細緻度不同,但底層的原理一樣。 | *以此類推,雖然曲線細緻度不同,但底層的原理一樣。 | ||
− | === | + | ===動畫=== |
*共通屬性: | *共通屬性: | ||
*#attributeName: | *#attributeName: | ||
行 333: | 行 333: | ||
− | [[分類: | + | [[分類:資訊基礎應用]] |
於 2020年11月22日 (日) 21:48 的修訂
目錄
群組
- 上面的文字與方塊已經算是一個群組了,接下來可以在<g>這個元素,使用變形(transform)來一起改變外觀
- 就算有設定<g>的x,y值,但就是完全沒有反應,如果要控制<g>的位置,就要用transform了。
- 利用transform=”translate(40 20)”,就可以位移了,這用法和CSS3 transform相當接近,雖然類似x,y但本質上還是有所不同。
<svg width="100%" height="150"> <g transform="rotate(-10)"> <rect y="10" width="100" height="100" style="stroke: #777; stroke-width: 3; fill: #07B492;"/> <text x="0" y="130" style="stroke: pink; fill: white"> SVG</text> </g> </svg>
- 像以上這樣,<g>群組就會被旋轉(-10 deg)。
- 在G裡面的元素,都會被外層<g>所設定的樣式影響,像以下內部的元素沒有設定外框,但卻可以繼承其父層的<g>樣式。
- 也就像CSS一樣,如果子元素有設定,則子元素優先。
<svg width="100%" height="150"> <g style="stroke: pink; stroke-width: 5px"> <circle cx="40" cy="35" r="30" style="fill: white;"/> <circle cx="120" cy="35" r="30" style="fill: white;"/> <rect x="160" y="5" width="40" height="40" style="fill: white;"/> <rect x="220" y="5" width="40" height="40" style="fill: red;"/> </g> </svg>
不過我沒想到的是,svg還可以這樣用,在<g>裡面再放一個<svg>,這樣就可以設定他的x,y,這招太絕了,這樣就可以避免使用translate,使用x,y來設定位置。
<svg width="100%" height="150"> <g> <svg x="40" y="20"> <rect y="10" width="100" height="100" style="stroke: #777; stroke-width: 3; fill: #07B492;"/> <text x="0" y="130" style="stroke: pink; fill: white"> SVG</text> </svg> </g> </svg>
定義一次,引用多次
- defs 顧名思義就是「definitions」:定義,我們可以把許多重複性質高的元素,放入 defs 元素內,讓它變成一個可以重複利用的物件,原理就有點類似當年 flash 裏頭把一些動畫或是圖案轉換成物件一樣;首先我們來看到最常見的 defs 例子:「重複的圖形」,下面利用 defs 定義了一個矩形的長寬顏色,再使用 use 元素把矩形表現在畫面上,而 use 元素具有 x 與 y 的座標屬性,就可以輕鬆的做出許多不同位置的矩形。
<defs> <rect id="rect1" width="100" height="50" x="10" y="10" fill="#c00"/> </defs> <use xlink:href="#rect1"/> <use xlink:href="#rect1" x="110"/>
也可以將 g 元素 ( 群組 ) 放在 defs 元素裏頭:
<defs> <g id="g1"> <rect id="rect1" width="100" height="50" x="10" y="10" fill="#c00"/> <circle id="circle1" cx="30" cy="30" r="10" fill="#00c"/> </g> </defs> <use xlink:href="#g1"/> <use xlink:href="#rect1" x="110"/> <use xlink:href="#circle1" x="210"/>
定義漸層色
<defs> <linearGradient id="a1"> <stop offset="5%" stop-color="#F00" /> <stop offset="95%" stop-color="#ff0" /> </linearGradient> </defs> <rect x="50" y="250" width="100" height="100" stroke="#000" stroke-width="5" fill="url(#a1)"></rect> <circle cx="220" cy="300" r="50" stroke="#000" stroke-width="5" fill="url(#a1)"></circle> <rect x="290" y="250" width="100" height="100" stroke="url(#a1)" stroke-width="5" fill="none"></rect>
文字路徑(先把貝茲曲線定義好,再把文字套入)
<defs> <path id="a1" d="M0 50 C150 150 100 -50 300 50" stroke="#000" fill="none"/> </defs> <text> <textPath xlink:href="#a1">這是隨著路徑跑的文字 </textPath> </text>
使用 defs 定義 filter(把漸層或濾鏡變為ID就能放進矩形、圓形等等圖形中)
<defs> <filter width="200" height="200" x="0" y="0" id="blur" filterUnits="userSpaceOnUse"> <feGaussianBlur stdDeviation="5" /> </filter> </defs> <rect x="30" y="30" width="70" height="70" fill="#a00" filter=url("#blur") />
一朵花的程式碼
<rect x="95" y="100" style="width:10;height:200;fill:green;"/> <polygon points="100,110 120,20 100,10 80,20" stroke="yellow" stroke-width="1" fill="#00a0e9"/> <polygon points="100,110 120,20 100,10 80,20" transform="rotate(45 100 100 )" stroke="yellow" stroke-width="1" fill="#00a0e9"/> <polygon points="100,110 120,20 100,10 80,20" transform="rotate(90 100 100 )" stroke="yellow" stroke-width="1" fill="#00a0e9"/> <polygon points="100,110 120,20 100,10 80,20" transform="rotate(135 100 100 )" stroke="yellow" stroke-width="1" fill="#00a0e9"/> <polygon points="100,110 120,20 100,10 80,20" transform="rotate(180 100 100 )" stroke="yellow" stroke-width="1" fill="#00a0e9"/> <polygon points="100,110 120,20 100,10 80,20" transform="rotate(225 100 100 )" stroke="yellow" stroke-width="1" fill="#00a0e9"/> <polygon points="100,110 120,20 100,10 80,20" transform="rotate(270 100 100 )" stroke="yellow" stroke-width="1" fill="#00a0e9"/> <polygon points="100,110 120,20 100,10 80,20" transform="rotate(315 100 100 )" stroke="yellow" stroke-width="1" fill="#00a0e9"/> <circle cx="100" cy="100" r="50" fill="#FF8000"/> <circle cx="85" cy="85" r="4" fill="blac k"/> <circle cx="115" cy="85" r="4" fill="black"/> <circle cx="100" cy="100" r="4" fill="black"/> <path d="M 85,130 Q 100,145 115,130" style="stroke:black;fill:none;"/>
- 花瓣
漸層
漸層的類型有兩種,線形漸層和放射形漸層。線形漸層沿直線變化,在 defs元素裡創建一個 <linearGradient> 元素,就創建了一個線形漸層。漸變必須有一個id屬性,否則它不能被其他元素引用,等於白做了。
- 漸層由一種以上的顏色所組成,由一種顏色慢慢轉成另一種顏色,設定好顏色之後,再以ID的形式給漸層。
- 漸層(又稱為「漸變」)是指將構成元素的形狀或色彩做次第改變的層層變化。例如,同一種形狀的漸大或漸小、同一種色彩的漸濃或漸淡,均屬於漸層的形式變化,而在這些漸增或漸減的層次變化中,即能具現出漸層的美感。
- 漸變的基本原理與反覆相類似,但由於其中或形或色的漸次改變,使得畫面較具活潑性,予人生動輕快的感受。中國建築中的寶塔;樂曲中音量的漸強漸弱;文學小說中情節高潮的堆且;大會舞隊型的漸次縮小或擴大……等,都是漸層形式原理的例子。
(一)線性漸層
在上面的例子裡,一個線形漸層被用在<rect>元素上,線形漸層內部有若干 <stop> 節點,它們用來指定漸變應該在什麼位置形成什麼顏色,其中兩個屬性分別是:定義偏移位置的offset屬性和定義顏色的stop-color屬性。另外,它們可以直接設置,或通過CSS設置。上面的例子裡混合使用了這兩種形式。比如,這個例子的漸變是從紅色開始,到中間漸變成黑色,最後漸變到藍色。你可以按照自己的想法設置各種stop-color,但是它們的offset必須是從0%逐漸提高到100%。(如果不加%,就是0-1)。如果有重複的值,不會被分配到xml樹的最後。另外像fill和stroke一樣,你也可以設置一個stop-opacity屬性表示透明度。
<?xml version="1.0" standalone="no"?> <svg width="120" height="240" version="1.1" xmlns="http://www.w3.org/2000/svg"> <defs> <linearGradient id="Gradient1"> <stop class="stop1" offset="0%"/> <stop class="stop2" offset="50%"/> <stop class="stop3" offset="100%"/> </linearGradient> <linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1"> <stop offset="0%" stop-color="red"/> <stop offset="50%" stop-color="black" stop-opacity="0"/> <stop offset="100%" stop-color="blue"/> </linearGradient> <style type="text/css"><![CDATA[ #rect1 { fill: url(#Gradient1); } .stop1 { stop-color: red; } .stop2 { stop-color: black; stop-opacity: 0; } .stop3 { stop-color: blue; } ]]></style> </defs> <rect id="rect1" x="10" y="10" rx="15" ry="15" width="100" height="100"/> <rect x="10" y="120" rx="15" ry="15" width="100" height="100" fill="url(#Gradient2)"/> </svg>
- 在上面的例子裡,一個線形漸層被用在<rect>元素上,線形漸層內部有若干 <stop> 節點,它們用來指定漸變應該在什麼位置形成什麼顏色,其中兩個屬性分別是:定義偏移位置的offset屬性和定義顏色的stop-color屬性。另外,它們可以直接設置,或通過CSS設置。上面的例子裡混合使用了這兩種形式。比如,這個例子的漸變是從紅色開始,到中間漸變成黑色,最後漸變到藍色。你可以按照自己的想法設置各種stop-color,但是它們的offset必須是從0%逐漸提高到100%。(如果不加%,就是0-1)。如果有重複的值,不會被分配到xml樹的最後。另外像fill和stroke一樣,你也可以設置一個stop-opacity屬性表示透明度。
- 使用漸變時,我們需要在對象的fill或stroke屬性裡引用它。就像在CSS里通過url來引用其他元素一樣,在這裡,url引用的是我們給漸變設置的id,所以只需要將fill屬性設置成url(#Gradient) ,我們的對象就可以呈現出五彩斑斕的效果。另外你也可以給stroke進行同樣的設置。
- <linearGradient>元素還可以設置其他一些屬性,用來定義尺寸和样式。比如漸變的方向是由兩個點控制的,它們用x1, x2,y1,y2四個屬性控制,形成一條直線,漸變就沿這條直線變化。漸變默認的方向是水平方向,使用這些屬性就可以改變方向。上面例子裡的Gradient2就是一個垂直的漸變。
(二)放射漸層
放射形漸層很類似線形漸層,只不過是從一個點向外發散漸變。在文檔的 defs 段落裡增加一個 <radialGradient> 元素,就可以創建放射形漸層。
<?xml version="1.0" standalone="no"?> <svg width="120" height="240" version="1.1" xmlns="http://www.w3.org/2000/svg"> <defs> <radialGradient id="Gradient1"> <stop offset="0%" stop-color="red"/> <stop offset="100%" stop-color="blue"/> </radialGradient> <radialGradient id="Gradient2" cx="0.25" cy="0.25" r="0.25"> <stop offset="0%" stop-color="red"/> <stop offset="100%" stop-color="blue"/> </radialGradient> </defs> <rect x="10" y="10" rx="15" ry="15" width="100" height="100" fill="url(#Gradient1)"/> <rect x="10" y="120" rx="15" ry="15" width="100" height="100" fill="url(#Gradient2)"/> </svg>
- 這個例子的裡,放射形漸層中的stop節點在用法上和前面的線形漸層一樣,但是這裡的圖形對像是中間呈紅色,然後向各個方向發散漸變,直到邊緣漸變到藍色。放射形漸層<radialGradient>也有若干用來定義位置和方向的屬性,不過與線形漸層不同,這裡的設置會稍微複雜一點。放射形漸層裡也可以設置兩個點,用來確定它的範圍。第一個點用來定義一個環,限定漸變的範圍。該點包括坐標屬性cx和cy,以及半徑屬性r。定義這三個屬性,就可以改變漸變的位置和大小,就像上面例子裡的第二個漸變效果。
- 第二個點被稱為焦點,通過坐標屬性fx和fy來確定。第一個點決定的是漸變所處的範圍,而焦點則決定漸變的中心。
<?xml version="1.0" standalone="no"?> <svg width="120" height="120" version="1.1" xmlns="http://www.w3.org/2000/svg"> <defs> <radialGradient id="Gradient" cx="0.5" cy="0.5" r="0.5" fx="0.25" fy="0.25"> <stop offset="0%" stop-color="red"/> <stop offset="100%" stop-color="blue"/> </radialGradient> </defs> <rect x="10" y="10" rx="15" ry="15" width="100" height="100" fill="url(#Gradient)" stroke="black" stroke-width="2"/>
<circle cx="60" cy="60" r="50" fill="transparent" stroke="white" stroke-width="2"/> <circle cx="35" cy="35" r="2" fill="white" stroke="white"/> <circle cx="60" cy="60" r="2" fill="white" stroke="white"/> <text x="38" y="40" fill="white" font-family="sans-serif" font-size="10pt">(fx,fy)</text> <text x="63" y="63" fill="white" font-family="sans-serif" font-size="10pt">(cx,cy)</text> </svg>
- 如果焦點被移動到漸變範圍之外,漸變不可能被正確渲染,所以會被重定義到範圍的邊緣。如果不定義焦點,則默認與漸變範圍的中點是同一點。
- 兩種漸變都可以通過一些屬性,定義諸如變形等樣式。在這裡僅提其中一個:spreadMethod屬性。當漸變已經到達範圍邊緣,但圖形對像還沒被完全填充時,這一屬性將決定接下來會發生什麼。它有三個可用值,"pad", "reflect", 以及 "repeat"。 "pad"的效果你已經看到過了,當漸變到達範圍邊緣,最後一個顏色將用來填充圖形剩下的區域。 "reflect"是繼續漸變,但是會從100%處的顏色漸變會0%的位置,然後再翻過來繼續。 "Repeat"也是讓漸變繼續,不過是跳過返回的過程,直接回到起始狀態,然後重新漸變。
- 柔焦濾鏡與放射漸層的練習
柔焦濾鏡
feGaussianBlur(柔焦濾鏡)應該算是 SVG filter 裏頭最簡單的濾鏡,因為它只有一個參數需要注意:stdDeviation,這也是控制模糊程度的參數,數字越大越模糊,數字為零則是圖片原本的狀態,在這邊有一個比較需要注意的地方,就是要記得設定 filter 的filterUnits為 userSpaceOnUse ,因為預設值是會讓 filter 跟隨著套用該 filter 的物件跑,所以要記得設定成跟隨整個 SVG space。
<?xml version='1.0' encoding='UTF-8' standalone='no'?> <svg xmlns='http://www.w3.org/2000/svg' version='1.1' width='160' height='160'> <defs> <radialGradient id='r4' cx='50%' cy='50%' r='50%' > <stop style='stop-color:#fff100' offset='0%' /> <stop style='stop-color:#ff9900;stop-opacity:.98' offset='50%' /> <stop style='stop-color:#ff1700;stop-opacity:.98' offset='100%' /> </radialGradient> <filter id='f1' > <feGaussianBlur stdDeviation='3' /> </filter> </defs> <circle cx='79' cy='79' r='75' style="fill:url(#r4);filter:url(#f1);" /> </svg>
feGaussianBlur後面的stdDeviation='3'用來設定模糊的程度,0就是完全沒有改變。
path
用參數(0~1)和控制點作圖:
- 一次:
- 二次:
- 三次:
- 四次:
- 五次:
path示範
標籤:
- set(開關)
- 只用attributeName,to,begin三屬性
- animate(屬性連續改變)
- animateTransform(平移,旋轉,縮放)
- animateMotion(循跡運動)
- 共通語法:將母圖形分拆成開始和結束兩標籤,中間插入動畫標籤。
- 共通屬性:
- attributeName:
- set,animate為某一個母圖形的屬性。from 和 to 就是這個屬性的值將由多少變到多少。
- animateTransform為'transform'另搭配 type 屬性
- animateMotion免設此屬性
- type屬性之值(animateTransform專用):
- rotate旋轉,影響屬性from='起始角度,旋轉軸心x座標,旋轉軸心y座標'、to='結束角度,旋轉軸心x座標,旋轉軸心y座標'。
- scale縮放,影響屬性from='x起始倍率,y起始倍率'、to='x結束倍率,y結束倍率',倍率是自左上原點開始算,如果同組x,y倍率相同,可以只寫一個值。
- translate平移,影響屬性from='起始原點x座標,起始原點y座標'、to='結束原點x座標,結束原點y座標'。
- skewX X軸不動,X軸下方向右歪斜,影響屬性from='起始歪斜角度'、to='結束歪斜角度'
- skewY Y軸不動,Y軸右方向下歪斜,影響屬性from='起始歪斜角度'、to='結束歪斜角度'
- begin='幾s':幾秒開始跑,通常設為 0s 。
- dur='幾s':跑一輪要幾秒,可以設為 indefinite 。
- repeatCount='幾':要跑幾輪,indefinite代表無限多輪,預設值為1。
- from 開始狀態(animate,animateTransform有)。
- to 結束狀態(set,animate,animateTransform有)。
- path(animateMotion專用) 屬性為移動路徑:由 m 開始
- rotate='auto'(animateMotion專用) 圖形隨路徑曲度而轉折。
- attributeName:
貝茲曲線
在數學的數值分析領域中,貝茲曲線(英語:Bézier curve,亦作「貝塞爾」)是計算機圖形學中相當重要的參數曲線。更高維度的廣泛化貝茲曲線就稱作貝茲曲面,其中貝茲三角是一種特殊的實例。 貝茲曲線於1962年,由法國工程師皮埃爾·貝茲(Pierre Bézier)所廣泛發表,他運用貝茲曲線來為汽車的主體進行設計。貝茲曲線最初由Paul de Casteljau於1959年運用de Casteljau演算法開發,以穩定數值的方法求出貝茲曲線。
二次貝茲曲線
貝茲曲線的程式碼
<path id='a1' d='M0,50 C150,130 100,0 300,40' style='stroke:#000;fill:none;' />
- 用貝茲曲線設定文字要先在<def></def>寫好,再使用id匯入。
- 所以只需要設定一次,就可以使用設好的ID使用多次。
- 我可以在每一個<textPath></textPath>中放上不一樣的文字,就會有一樣的角度,不同的樣貌
程式碼如下(此為文字)
<textPath startOffset='4%' xlink:href='#a1' style='font-family:KaiTi;fill:pink;font-size:40px'></textPath>
純貝茲曲線指令碼
<path d='M0,0 Q50,50 20,0 T40,0 60,0 80,0 100,0 120,0 140,0 160,0 180,0 200,0' style='stroke:black;fill:none;' transform='translate(0,50)'/>
三次貝茲曲線
三次的程式碼
<path d='M0,50 C50,100 80,0 200 50' style='stroke:blue;fill:none;' />
- 三次與兩次相比更加細緻。
三次與數次貝茲曲線的差異
- 以此類推,雖然曲線細緻度不同,但底層的原理一樣。
動畫
- 共通屬性:
- attributeName:
- set,animate為某一個母圖形的屬性。from 和 to 就是這個屬性的值將由多少變到多少。
- animateTransform為'transform'另搭配 type 屬性
- animateMotion免設此屬性
- type屬性之值(animateTransform專用):
- rotate旋轉,影響屬性from='起始角度,旋轉軸心x座標,旋轉軸心y座標'、to='結束角度,旋轉軸心x座標,旋轉軸心y座標'。
- scale縮放,影響屬性from='x起始倍率,y起始倍率'、to='x結束倍率,y結束倍率',倍率是自左上原點開始算,如果同組x,y倍率相同,可以只寫一個值。
- translate平移,影響屬性from='起始原點x座標,起始原點y座標'、to='結束原點x座標,結束原點y座標'。
- skewX X軸不動,X軸下方向右歪斜,影響屬性from='起始歪斜角度'、to='結束歪斜角度'
- skewY Y軸不動,Y軸右方向下歪斜,影響屬性from='起始歪斜角度'、to='結束歪斜角度'
- begin='幾s':幾秒開始跑,通常設為 0s 。
- dur='幾s':跑一輪要幾秒,可以設為 indefinite 。
- repeatCount='幾':要跑幾輪,indefinite代表無限多輪,預設值為1。
- from 開始狀態(animate,animateTransform有)。
- to 結束狀態(set,animate,animateTransform有)。
- path(animateMotion專用) 屬性為移動路徑:由 m 開始
- rotate='auto'(animateMotion專用) 圖形隨路徑曲度而轉折。
- attributeName:
向前移動並消失的程式碼
<?xml version='1.0' encoding='UTF-8' standalone='no'?> <svg xmlns='http://www.w3.org/2000/svg' version='1.1' height='400' width ='1000'> <defs> <linearGradient id='LG' x1='30%' y1='0%' x2='70%' y2='0%'> <stop offset='0%' style='stop-color:#ffff00;stop-opacity:1' /> <stop offset='100%' style='stop-color:#ff0000;stop-opacity:1' /> </linearGradient> </defs> <circle cx="30" cy="30" r="25" style="stroke: none; fill:url(#LG);"> <animate attributeName="cx" attributeType="XML" from="30" to="1020" begin="0s" dur="3s" fill="remove" repeatCount="indefinite"/> <animate attributeType="CSS" attributeName="opacity" from="1" to="0" dur="3s" repeatCount="indefinite" /> </circle> </svg>
圖形範例
綜合應用:
三角形:
直角三角形:
動畫:
旋轉:
三個方塊的舞蹈:
互動: