相信大家在Flash時代見過很多通過Flash動畫模擬毛筆書寫效果的教程,但在Flash早已停止被支持的今天,“暢想資源”便來教教大家如何通過SVG和CSS動畫簡單實現動畫書寫毛筆字效果,讓訪客在移動設備和不支持Flash的瀏覽器(即現今絕大多數瀏覽器 )中也一樣能看到毛筆字書寫效果,為你的網站加入中國傳統文化色彩。
預覽
“暢想資源”個人網站首頁:https://www.hesyifei.com/(或點擊下方“Run”按鈕預覽)
See the Pen 利用純SVG+CSS keyframes animation動畫實現手寫毛筆字(書法)效果:預覽 by Yifei He (@hesyifei) on CodePen.
一、準備毛筆字SVG源文件
1、既然要利用純SVG+CSS動畫實現動畫書寫毛筆字效果,我們當然首先需要一個以SVG路徑(path)形式保存的毛筆字文件。
我們在這裡將使用“書法迷”網站上所提供的SVG文件,大家亦可自行於紙上寫完毛筆字後掃描,再將每筆的邊緣轉換為閉合路徑並存為SVG文件。
提示:本文中為方便期間將只使用一個字(“非”)來進行教程,實際操作中可以同樣方法使用更多字來製成整個動畫(參見上方預覽動畫的原始碼)。
二、切分每一筆畫
1、接下來我們需要將毛筆中每一筆畫單獨切分開來。
我們本文中將使用Adobe Illustrator CC做示範,但你也可以使用你熟悉的其它SVG工具達成相同效果。
2、首先我們可以把所有背景刪除,再把所有圖層都移動到根部,這樣可以避免SVG中保有任何 g transform
等標籤,使得所有路徑都清楚地保存在SVG文件中,讓之後的步驟更加順利。
3、接着我們便可以正式開始切割筆畫了,“暢想資源”找到AI中一個比較方便的“美工刀”(Knife),但大家也可能有更快更方便的方法。這裡“暢想資源”就不詳細介紹如何使用“美工刀”,可自行尋找AI相關教程。
4、對於沒有重疊的筆畫來說(即字中其它筆畫不會碰到這一筆畫,比如下圖中“非”字的右半部份的筆畫),切割十分簡單,只需要將兩個部分分開來即可。
5、對於有重疊部分的筆畫來說(即字中其它筆畫會重複覆蓋這一筆畫,比如下圖中的“非”字的左下角那一個筆畫),切割時就需要先複製(duplicate)那一圖層,然後再想辦法把兩個重疊的筆畫分開切割,從而讓各自都能保留一個完整的筆畫。
6、切割完成後,將每個圖層命名為可以理解的名字,比如“非”的第一筆可以被叫做“fei-1”。
7、用純文字編輯器打開SVG文件,檢查是否整個文件是否只剩下 path
標籤,沒有 g
等其它標籤(style
標籤可以保留),如有問題請參見上方第2步。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
<?xml version="1.0" encoding="utf-8"?> <!-- Generator: Adobe Illustrator 21.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 128 128" style="enable-background:new 0 0 128 128;" xml:space="preserve"> <style type="text/css"> .st0{fill:#CC3300;} </style> <path id="fei-1" class="st0" d="M47.9,76.4c-0.4-0.9-1-2-0.2-2.9c1.1-1.1,2.3-2.3,3.8-2.6c-0.4-1.7,0.8-3.4,0.8-5.1 c-0.3-1.2-0.8-2.3-1-3.5c0.3-1,0.8-1.9,1.1-2.8c-0.4-0.1-0.8-0.2-1.2-0.3c0.9-4.9,0.1-10,0.4-15c0.2-1.2,1-2.3,1.1-3.6 c-0.1-0.7-0.6-1.3-0.9-1.9c-1.1-1.8-1.5-3.8-2.7-5.5c-1.3-1.7-2.5-3.5-3.7-5.2c-0.8-1.2-2.3-1.6-3.6-2.1c-0.2,1.1-0.6,2.2-0.7,3.3 c0.1,1.5,0.4,3.1,0.1,4.7c-0.4,2.5-0.5,5.1-0.3,7.7c-0.4,0.4-0.8,0.9-1.2,1.3c-0.1,0-0.1,0-0.2-0.1l0.4,11c0.1,0,0.1,0,0.2,0 c-0.6,3.3-0.5,6.7-0.5,10c-0.1,0-0.1,0-0.2,0L38.7,71c0,0,0,0,0.1,0c0.4,1,1.4,1.8,1.1,2.9c-1,1.5-2.4,2.9-2.6,4.8 c-0.3,1.4,0.8,2.4,1,3.7c0,0-0.1,0.1-0.1,0.1l6.8,10.8c0,0,0,0,0,0c1,0.3,2,0.6,3,0.7c0.7,0.4,1.4-0.1,1.8-0.6 c0.9-1.4,2-2.6,3.1-3.9c-0.1-1.8,0.1-3.6,0.6-5.4l-5.5-7.7C48,76.4,47.9,76.4,47.9,76.4z"/> <path id="fei-2" class="st0" d="M25.9,59c1-0.8,1.5-2.1,2.6-3c1.1-0.5,2.4-0.4,3.5-0.9c0.8-0.5,1.2-1.5,2.2-1.6 c1.9-0.4,3.8,0,5.7,0.3l-0.4-11c-1.2-0.5-2.4-1-3.7-1.1c-3.3-0.4-6.6-1.1-10-1c-0.7,1.3-1.5,2.5-2.6,3.5c-1.5,1-3.2,1.6-4.9,2.2 c0,1.6,1.3,2.9,2.8,3.1c1.3,0.4,3.1,0.6,3.6,2.1c-0.7,2.6-3.2,4.6-3.4,7.5c-0.4,1.1,0.1,2.1,0.7,3c0,0,0,0,0,0l0.9,0.5 C22.8,60.8,24.7,60,25.9,59z"/> <path id="fei-3" class="st0" d="M65.1,65.8c-3.6,2.2-6.7,5-10.2,7.2c-2.2,1.4-4.4,2.9-7,3.4l-9.7,5.9c0,0.1,0,0.1,0,0.2 c-1.4,1.5-3,2.8-4.6,4.1c-1.2,0.7-2.4,1.3-3.6,2c-1.4,0.9-3.1,0.9-4.6,1.7c-0.8,0.9-1.8,1.6-3,1.7c-0.4-1.3-0.9-2.8-0.2-4.2 c0.7-1.3,1.4-2.6,2.4-3.7c0.8-1,2.1-1.5,2.8-2.5c1.5-1.7,2.6-3.7,4-5.5c2-2.2,4.6-3.8,7.2-5.2l0.7-7.2c-1.6,0-2.9-1.1-4.5-1.2 c-1.8-0.2-3.4-1.2-5.1-1.7c-1.4,0.2-2.7,1-4,1.6c-0.9,0.4-2,0.2-2.9,0.2c0,0,0-0.1,0-0.1L21.9,62c-0.9,0.1-2,0.2-2.3,1.2 c-0.6,1.4,0.3,2.7,1,3.8c0.7,1.8,2.5,2.9,3.9,4.1c-0.2,1.1-0.1,2.1-0.2,3.2c-0.1,1.3-0.8,2.5-1.5,3.6c-1,1.4-1.1,3.1-1.9,4.6 c-1.3,2.9-3.5,5.2-5.3,7.7c-0.8,2.3-0.8,4.9,0,7.2c0.5,0.8,1.2,1.5,2,2c1.9,1,3,2.9,4.3,4.5c0.3-0.1,0.6-0.2,0.9-0.3 c0.9,1,2.2,1.1,3.4,1.5c0.9,0.5,1.7,1.6,2.9,1.2c1.9-0.1,3.9-0.2,5.5-1.4c2.2-1.2,3.9-3.2,5.7-5c2-1.8,1.9-5.2,4.5-6.5l8.6-9 c0-0.1,0.1-0.2,0.1-0.3c0.8-1.2,2-2,2.9-3.2c0.8-1.1,1.5-2.3,2.5-3.3c0.9-0.3,2-0.1,2.9-0.4c-0.2-0.5-0.4-1-0.5-1.5 c0.5-0.3,1-0.6,1.4-1.1c1.5-2,2.6-4.2,3.5-6.5c0.4-0.9,1.2-1.7,1.6-2.7C66.8,65.4,65.9,65.4,65.1,65.8z"/> <path id="fei-4" class="st0" d="M83.9,75.5c0.3-1.6-1.3-2.8-1-4.3c0.3-1.9,0.8-3.7,1.1-5.6c0,0,0,0,0,0l0.3-5.3 c-0.5-1.6-0.6-3.4-0.1-5c0.4-1.2,0.2-2.5,0-3.8c0,0,0,0,0.1,0l0.3-1.8c0,0,0,0-0.1,0.1c0-0.9,0.1-1.8,0.3-2.7c0,0,0,0,0,0l-0.5-8 c0,0-0.1,0-0.1,0c0-3.6-0.1-7.3,0.5-10.9c0.5-2.1,2.4-4.2,1.1-6.4c-0.5-1.1-1-2.1-1.8-3c-1-0.8-2.3-0.9-3.4-1.2 c-2.2-0.6-4.5-1-6.7-0.3c-1.4,1.1-2.6,2.4-3.8,3.7c-1.3,1.3-1.8,3-2.3,4.7c1.5,0.6,3,0.8,4.6,0.5c1-0.2,1.4,1,1.7,1.7 c0,2.8,0,5.6,0,8.4c-0.2,2.5-0.1,5,0.4,7.4c0,1.9-0.4,3.9,0.1,5.8c0.2,0.8,0.2,1.7,0,2.6c-0.4,2.9-0.4,5.9-0.9,8.8 c-0.4,4.5,0.4,8.9,0.6,13.4c-0.2,1.9,0.5,3.7,0.5,5.5c0.7,2.1-0.9,4-0.5,6c0.4,1.9,1.2,3.8,1.2,5.8c-0.9,0.7-2.1,1.2-2.8,2.1 c-0.4,1.8-0.7,3.8-2.1,5.2c0.9,0.9,1.7,2,2.3,3.2c1.3,3,2.7,6,5,8.3c0.7,0.8,1.9,0.4,2.8,0.4c1.7,0.3,2.8-1.1,3.5-2.4 c0.9-2.6,0.5-5.3,0.1-7.9c-0.3-1.5,0.1-3.1-0.3-4.6c-0.4-2.9-0.5-6,0.6-8.8c0,0,0,0,0,0l-0.5-7.5C83.2,78.5,83.9,76.9,83.9,75.5z"/> <path id="fei-5" class="st0" d="M85.8,47.3c-0.2,0.9-0.5,1.7-1.2,2.3l-0.3,1.8c1.4-0.3,2.9-0.3,4.4-0.5c1.5-1.8,3.4-3.4,5.7-3.9 c1.9-0.1,3.8-0.2,5.7-0.6c1.2-0.8,2.6-1.7,3.2-3.1c-0.2-1.7-1.6-2.9-2.5-4.2c-1.9-1.3-4.3-1.4-6.5-1.6c-1.3-0.1-2.6-0.5-4-0.4 c-2.1,0.2-4,1.2-6,1.8l0.5,8C85.2,47.1,85.5,47.2,85.8,47.3z"/> <path id="fei-6" class="st0" d="M88.3,68.2c-0.2,2.4-1.1,4.7-1.1,7.2c0.5,0.1,1,0.2,1.5,0.2c3.3-0.9,5.4-3.8,8.3-5.4 c0.9-0.8,2.2,0.7,3.1-0.3c1.1-1.1,2.6-2,3.3-3.4c0.1-2.9-2.7-5.4-5.5-5.6c-1.7-0.3-3.1-1.2-4.7-1.9c-1-0.4-2-0.1-3,0.1 c-1.9,0.5-3.9,0.9-5.9,1.2c0,0,0-0.1,0-0.1l-0.3,5.3C85.7,65.6,88.2,66.2,88.3,68.2z"/> <path id="fei-7" class="st0" d="M110.8,85.7c-0.4-1.4-2-1.9-3.1-2.6c-1.3-0.9-2.4-2-3.7-2.8c-2.3-1.7-5.3-1.3-7.9-0.6 c-2.7,1.1-5.7,1.2-8.6,0.9c-1.1-0.2-2.5,0.1-3.3-0.9c0,0,0,0,0-0.1l0.5,7.5c0.8,0.6,1.5,1.2,2.3,1.8c-0.5,0.3-1,0.7-1.5,1 c0.7,2.3,2.4,4.1,4.4,5.3c1.1,0.3,2.3,0,3.4,0c2.6-0.1,5.1-1.1,7.8-1c0.9-0.1,1.6,0.4,2.4,0.7c1.2-0.2,2.2-1,3.4-1.1 c2.1,0.1,3.8-1.4,5.8-1.8C111.8,90.1,111.3,87.9,110.8,85.7z"/> </svg> |
三、加入筆序路徑
1. 在切割完成後,我們還需要讓電腦知道他該按照什麼路徑、什麼順序來播放每一筆筆畫。
2. 首先,選取“鉛筆工具”(Pencil Tool),記得在頂部把這個path的顏色調為“無”(即透明)。
3. 然後依照毛筆手寫時的筆序和方向,分別畫出每個筆畫的路徑,這一路徑應在那筆筆畫的正中間。
注意:這一路徑最好在起點可超出最初有墨的地方,否則最後顯示時那一筆的第一點將突然出現而不是漸漸加入。
提示:如果這一筆畫屬於剛剛“二-5”步中有重疊部分的筆畫,也記得將筆畫當作單獨的兩筆來處理。
4. 將新加入的每個圖層(即每個路徑)命名為可以理解的名字,比如“非”的第一筆筆序可以被叫做“line-fei-1”。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<?xml version="1.0" encoding="utf-8"?> <!-- Generator: Adobe Illustrator 21.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 128 128" style="enable-background:new 0 0 128 128;" xml:space="preserve"> <style type="text/css"> .st0{fill:#CC3300;} .st1{fill:none;} </style> // ......(和第二部分結尾代碼相同) <path id="line-fei-1" class="st1" d="M49.9,21.9C47,36,44.9,50.3,43.6,64.6c-0.6,6.5-1.1,13.2,0.7,19.6c1,3.4,3,7,6.4,7.9"/> <path id="line-fei-2" class="st1" d="M13.8,56.9c3.8-0.8,6.5-4.3,10-5.9c1.9-0.9,4.1-1.2,6.2-1.5c7.2-1,14.4-2,21.6-0.8"/> <path id="line-fei-3" class="st1" d="M13.5,70c5.1,0.8,10.3,0.5,15.2-0.9c3.1-0.9,6.2-2.2,9.4-2.3c-7.8,3.3-13,10.8-16.7,18.4 c-1.1,2.3-2.1,4.7-2.2,7.3c0,2.6,1.1,5.3,3.5,6.4c1.7,0.8,3.8,0.6,5.6-0.2c1.8-0.8,3.3-2,4.8-3.2c2.7-2.2,5.4-4.4,8-6.6 c0.7-0.6,1.5-1.2,2.2-1.8c0.9-0.7,1.8-1.5,2.7-2.2c7.6-6.3,14.8-13,21.7-20"/> <path id="line-fei-4" class="st1" d="M62.8,19.4c2.4,0.3,4.9,0,7.3,0c2.4,0,5,0.5,6.9,2.1c2.9,2.6,3,7,2.9,10.9 c-0.6,17.3-0.7,34.7-0.4,52c0.1,2.5,0.1,5-0.2,7.5c-0.6,4.9-2.5,9.4-4.3,14"/> <path id="line-fei-5" class="st1" d="M77.7,45.4c1.9-1.4,4.2-1.9,6.5-2.3c2.9-0.5,5.8-1.1,8.7-1.1c2.9,0,5.9,0.4,8.5,1.8"/> <path id="line-fei-6" class="st1" d="M76.4,64.1c5.3-0.8,10.7-1.1,16.1-1c1.2,0,2.6,0.1,3.4,1.1c0.6,0.8,0.6,2,0.1,3s-1.2,1.7-2,2.4 c-2.2,2-4.4,4-6.5,6"/> <path id="line-fei-7" class="st1" d="M78,85.1c11.9-1.4,24.1,1,34.6,6.8"/> </svg> |
四、製作並調試動畫
1、首先,我們可創建一個HTML和一個CSS文件。注意SVG源代碼一定要保存在HTML頁內(即inline使用),而非作為單獨文件儲存並使用img加入。
2、我們要將每一個筆序(即上方第三部分做出的以“line-”開頭的一堆開放路徑)放入一個SVG代碼的根中,並給每個路徑加入 class="pen line-fei-1"
(這裡“line-fei-1”是你那一筆序的名稱)(代碼是下方代碼的2至12行)
2、再將每一筆畫(即上方第二部分做出的一堆封閉的路徑)加入SVG defs
內的每個 clipPath
中。clipPath
的ID便是你筆畫的名稱(比如“fei-1”)(代碼是下方代碼的14至67行)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
<svg id="calligraphy-content" viewBox="0 0 128 128"> <path class="pen line-fei-1" d="M49.9,21.9C47,36,44.9,50.3,43.6,64.6c-0.6,6.5-1.1,13.2,0.7,19.6c1,3.4,3,7,6.4,7.9"/> <path class="pen line-fei-2" d="M13.8,56.9c3.8-0.8,6.5-4.3,10-5.9c1.9-0.9,4.1-1.2,6.2-1.5c7.2-1,14.4-2,21.6-0.8"/> <path class="pen line-fei-3" d="M13.5,70c5.1,0.8,10.3,0.5,15.2-0.9c3.1-0.9,6.2-2.2,9.4-2.3c-7.8,3.3-13,10.8-16.7,18.4 c-1.1,2.3-2.1,4.7-2.2,7.3c0,2.6,1.1,5.3,3.5,6.4c1.7,0.8,3.8,0.6,5.6-0.2c1.8-0.8,3.3-2,4.8-3.2c2.7-2.2,5.4-4.4,8-6.6 c0.7-0.6,1.5-1.2,2.2-1.8c0.9-0.7,1.8-1.5,2.7-2.2c7.6-6.3,14.8-13,21.7-20"/> <path class="pen line-fei-4" d="M62.8,19.4c2.4,0.3,4.9,0,7.3,0c2.4,0,5,0.5,6.9,2.1c2.9,2.6,3,7,2.9,10.9 c-0.6,17.3-0.7,34.7-0.4,52c0.1,2.5,0.1,5-0.2,7.5c-0.6,4.9-2.5,9.4-4.3,14"/> <path class="pen line-fei-5" d="M77.7,45.4c1.9-1.4,4.2-1.9,6.5-2.3c2.9-0.5,5.8-1.1,8.7-1.1c2.9,0,5.9,0.4,8.5,1.8"/> <path class="pen line-fei-6" d="M76.4,64.1c5.3-0.8,10.7-1.1,16.1-1c1.2,0,2.6,0.1,3.4,1.1c0.6,0.8,0.6,2,0.1,3s-1.2,1.7-2,2.4 c-2.2,2-4.4,4-6.5,6"/> <path class="pen line-fei-7" d="M78,85.1c11.9-1.4,24.1,1,34.6,6.8"/> <defs> <clipPath id="fei-1"> <path d="M47.9,76.4c-0.4-0.9-1-2-0.2-2.9c1.1-1.1,2.3-2.3,3.8-2.6c-0.4-1.7,0.8-3.4,0.8-5.1 c-0.3-1.2-0.8-2.3-1-3.5c0.3-1,0.8-1.9,1.1-2.8c-0.4-0.1-0.8-0.2-1.2-0.3c0.9-4.9,0.1-10,0.4-15c0.2-1.2,1-2.3,1.1-3.6 c-0.1-0.7-0.6-1.3-0.9-1.9c-1.1-1.8-1.5-3.8-2.7-5.5c-1.3-1.7-2.5-3.5-3.7-5.2c-0.8-1.2-2.3-1.6-3.6-2.1c-0.2,1.1-0.6,2.2-0.7,3.3 c0.1,1.5,0.4,3.1,0.1,4.7c-0.4,2.5-0.5,5.1-0.3,7.7c-0.4,0.4-0.8,0.9-1.2,1.3c-0.1,0-0.1,0-0.2-0.1l0.4,11c0.1,0,0.1,0,0.2,0 c-0.6,3.3-0.5,6.7-0.5,10c-0.1,0-0.1,0-0.2,0L38.7,71c0,0,0,0,0.1,0c0.4,1,1.4,1.8,1.1,2.9c-1,1.5-2.4,2.9-2.6,4.8 c-0.3,1.4,0.8,2.4,1,3.7c0,0-0.1,0.1-0.1,0.1l6.8,10.8c0,0,0,0,0,0c1,0.3,2,0.6,3,0.7c0.7,0.4,1.4-0.1,1.8-0.6 c0.9-1.4,2-2.6,3.1-3.9c-0.1-1.8,0.1-3.6,0.6-5.4l-5.5-7.7C48,76.4,47.9,76.4,47.9,76.4z"/> </clipPath> <clipPath id="fei-2"> <path d="M25.9,59c1-0.8,1.5-2.1,2.6-3c1.1-0.5,2.4-0.4,3.5-0.9c0.8-0.5,1.2-1.5,2.2-1.6 c1.9-0.4,3.8,0,5.7,0.3l-0.4-11c-1.2-0.5-2.4-1-3.7-1.1c-3.3-0.4-6.6-1.1-10-1c-0.7,1.3-1.5,2.5-2.6,3.5c-1.5,1-3.2,1.6-4.9,2.2 c0,1.6,1.3,2.9,2.8,3.1c1.3,0.4,3.1,0.6,3.6,2.1c-0.7,2.6-3.2,4.6-3.4,7.5c-0.4,1.1,0.1,2.1,0.7,3c0,0,0,0,0,0l0.9,0.5 C22.8,60.8,24.7,60,25.9,59z"/> </clipPath> <clipPath id="fei-3"> <path d="M65.1,65.8c-3.6,2.2-6.7,5-10.2,7.2c-2.2,1.4-4.4,2.9-7,3.4l-9.7,5.9c0,0.1,0,0.1,0,0.2 c-1.4,1.5-3,2.8-4.6,4.1c-1.2,0.7-2.4,1.3-3.6,2c-1.4,0.9-3.1,0.9-4.6,1.7c-0.8,0.9-1.8,1.6-3,1.7c-0.4-1.3-0.9-2.8-0.2-4.2 c0.7-1.3,1.4-2.6,2.4-3.7c0.8-1,2.1-1.5,2.8-2.5c1.5-1.7,2.6-3.7,4-5.5c2-2.2,4.6-3.8,7.2-5.2l0.7-7.2c-1.6,0-2.9-1.1-4.5-1.2 c-1.8-0.2-3.4-1.2-5.1-1.7c-1.4,0.2-2.7,1-4,1.6c-0.9,0.4-2,0.2-2.9,0.2c0,0,0-0.1,0-0.1L21.9,62c-0.9,0.1-2,0.2-2.3,1.2 c-0.6,1.4,0.3,2.7,1,3.8c0.7,1.8,2.5,2.9,3.9,4.1c-0.2,1.1-0.1,2.1-0.2,3.2c-0.1,1.3-0.8,2.5-1.5,3.6c-1,1.4-1.1,3.1-1.9,4.6 c-1.3,2.9-3.5,5.2-5.3,7.7c-0.8,2.3-0.8,4.9,0,7.2c0.5,0.8,1.2,1.5,2,2c1.9,1,3,2.9,4.3,4.5c0.3-0.1,0.6-0.2,0.9-0.3 c0.9,1,2.2,1.1,3.4,1.5c0.9,0.5,1.7,1.6,2.9,1.2c1.9-0.1,3.9-0.2,5.5-1.4c2.2-1.2,3.9-3.2,5.7-5c2-1.8,1.9-5.2,4.5-6.5l8.6-9 c0-0.1,0.1-0.2,0.1-0.3c0.8-1.2,2-2,2.9-3.2c0.8-1.1,1.5-2.3,2.5-3.3c0.9-0.3,2-0.1,2.9-0.4c-0.2-0.5-0.4-1-0.5-1.5 c0.5-0.3,1-0.6,1.4-1.1c1.5-2,2.6-4.2,3.5-6.5c0.4-0.9,1.2-1.7,1.6-2.7C66.8,65.4,65.9,65.4,65.1,65.8z"/> </clipPath> <clipPath id="fei-4"> <path id="fei-4" class="st0" d="M83.9,75.5c0.3-1.6-1.3-2.8-1-4.3c0.3-1.9,0.8-3.7,1.1-5.6c0,0,0,0,0,0l0.3-5.3 c-0.5-1.6-0.6-3.4-0.1-5c0.4-1.2,0.2-2.5,0-3.8c0,0,0,0,0.1,0l0.3-1.8c0,0,0,0-0.1,0.1c0-0.9,0.1-1.8,0.3-2.7c0,0,0,0,0,0l-0.5-8 c0,0-0.1,0-0.1,0c0-3.6-0.1-7.3,0.5-10.9c0.5-2.1,2.4-4.2,1.1-6.4c-0.5-1.1-1-2.1-1.8-3c-1-0.8-2.3-0.9-3.4-1.2 c-2.2-0.6-4.5-1-6.7-0.3c-1.4,1.1-2.6,2.4-3.8,3.7c-1.3,1.3-1.8,3-2.3,4.7c1.5,0.6,3,0.8,4.6,0.5c1-0.2,1.4,1,1.7,1.7 c0,2.8,0,5.6,0,8.4c-0.2,2.5-0.1,5,0.4,7.4c0,1.9-0.4,3.9,0.1,5.8c0.2,0.8,0.2,1.7,0,2.6c-0.4,2.9-0.4,5.9-0.9,8.8 c-0.4,4.5,0.4,8.9,0.6,13.4c-0.2,1.9,0.5,3.7,0.5,5.5c0.7,2.1-0.9,4-0.5,6c0.4,1.9,1.2,3.8,1.2,5.8c-0.9,0.7-2.1,1.2-2.8,2.1 c-0.4,1.8-0.7,3.8-2.1,5.2c0.9,0.9,1.7,2,2.3,3.2c1.3,3,2.7,6,5,8.3c0.7,0.8,1.9,0.4,2.8,0.4c1.7,0.3,2.8-1.1,3.5-2.4 c0.9-2.6,0.5-5.3,0.1-7.9c-0.3-1.5,0.1-3.1-0.3-4.6c-0.4-2.9-0.5-6,0.6-8.8c0,0,0,0,0,0l-0.5-7.5C83.2,78.5,83.9,76.9,83.9,75.5z"/> </clipPath> <clipPath id="fei-5"> <path id="fei-5" class="st0" d="M85.8,47.3c-0.2,0.9-0.5,1.7-1.2,2.3l-0.3,1.8c1.4-0.3,2.9-0.3,4.4-0.5c1.5-1.8,3.4-3.4,5.7-3.9 c1.9-0.1,3.8-0.2,5.7-0.6c1.2-0.8,2.6-1.7,3.2-3.1c-0.2-1.7-1.6-2.9-2.5-4.2c-1.9-1.3-4.3-1.4-6.5-1.6c-1.3-0.1-2.6-0.5-4-0.4 c-2.1,0.2-4,1.2-6,1.8l0.5,8C85.2,47.1,85.5,47.2,85.8,47.3z"/> </clipPath> <clipPath id="fei-6"> <path id="fei-6" class="st0" d="M88.3,68.2c-0.2,2.4-1.1,4.7-1.1,7.2c0.5,0.1,1,0.2,1.5,0.2c3.3-0.9,5.4-3.8,8.3-5.4 c0.9-0.8,2.2,0.7,3.1-0.3c1.1-1.1,2.6-2,3.3-3.4c0.1-2.9-2.7-5.4-5.5-5.6c-1.7-0.3-3.1-1.2-4.7-1.9c-1-0.4-2-0.1-3,0.1 c-1.9,0.5-3.9,0.9-5.9,1.2c0,0,0-0.1,0-0.1l-0.3,5.3C85.7,65.6,88.2,66.2,88.3,68.2z"/> </clipPath> <clipPath id="fei-7"> <path id="fei-7" class="st0" d="M110.8,85.7c-0.4-1.4-2-1.9-3.1-2.6c-1.3-0.9-2.4-2-3.7-2.8c-2.3-1.7-5.3-1.3-7.9-0.6 c-2.7,1.1-5.7,1.2-8.6,0.9c-1.1-0.2-2.5,0.1-3.3-0.9c0,0,0,0,0-0.1l0.5,7.5c0.8,0.6,1.5,1.2,2.3,1.8c-0.5,0.3-1,0.7-1.5,1 c0.7,2.3,2.4,4.1,4.4,5.3c1.1,0.3,2.3,0,3.4,0c2.6-0.1,5.1-1.1,7.8-1c0.9-0.1,1.6,0.4,2.4,0.7c1.2-0.2,2.2-1,3.4-1.1 c2.1,0.1,3.8-1.4,5.8-1.8C111.8,90.1,111.3,87.9,110.8,85.7z"/> </clipPath> </defs> </svg> |
5、然後我們需要依次找出每個筆序的 stroke-dasharray
長度。暫時將每個筆畫的相應長度記錄下來即可。
在這裡“暢想資源”為大家準備了一個工具,只需於下方(先點擊右上角的“Edit on CodePen”)將你那個一個筆畫的path路徑粘貼進去並慢慢修改CSS中的 stroke-dasharray
,直到那一筆畫剛好顯示完(即當 stroke-dasharray
加1時,筆畫無變化;當 stroke-dasharray
減1時,筆畫長度有減少)。
See the Pen 利用純SVG+CSS keyframes animation動畫實現手寫毛筆字(書法)效果:尋找stroke-dasharray by Yifei He (@hesyifei) on CodePen.
使用方法:
可以用類似以下的方法記錄結果:
1 2 3 4 5 6 7 |
.line-fei-1:75 .line-fei-2:40 .line-fei-3:124 .line-fei-4:101 .line-fei-5:25 .line-fei-6:35 .line-fei-7:36 |
6、再接着我們便開始加入CSS keyframes動畫了。
首先,創建一個 .pen
的class,其中 stroke
可修改為你想要的顏色,而 stroke-width
之後可能會需要進行微調(見第“五-2”步),animation-duration
則決定了你整個動畫將要進行的時間,其它animation-
開頭的選項也可進行修改(詳細見相關文檔)。
1 2 3 4 5 6 7 8 9 10 11 12 |
.pen { fill: none; stroke: black; stroke-width: 12; stroke-linecap: round; stroke-linejoin: round; stroke-dashoffset: 0; animation-duration: 4s; animation-iteration-count: 1; animation-timing-function: ease; } |
7、加入每一筆序相應的class。clip-path
里是你SVG defs
中那一筆畫的ID,stroke-dasharray
是你剛剛第5步為這一筆序中測試並記錄下來的數字。animation-name
是之後步驟中將會加入的你這一筆序動畫的名稱。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
.line-fei-1 { clip-path: url(#fei-1); stroke-dasharray: 75; animation-name: draw-fei-1; } .line-fei-2 { clip-path: url(#fei-2); stroke-dasharray: 40; animation-name: draw-fei-2; } // ...以此類推... .line-fei-7 { clip-path: url(#fei-7); stroke-dasharray: 36; animation-name: draw-fei-7; } |
8. 將所有筆序都加入完成後,便可開始加入CSS keyframes。0%時那個 stroke-dashoffset
和你上方該筆序的 stroke-dasharray
是同一個值,每個動畫中上方的百分比代表開始時時間(即你第6步中設置的 animation-duration
)的百分比,下方的百分比代表結束時時間的百分比。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
@keyframes draw-fei-1 { 0% { stroke-dashoffset: 75; } 10% { stroke-dashoffset: 0; } } @keyframes draw-fei-2 { 0%, 10% { stroke-dashoffset: 40; } 20% { stroke-dashoffset: 0; } } // ...以此類推... @keyframes draw-fei-7 { 0%, 90% { stroke-dashoffset: 36; } 100% { stroke-dashoffset: 0; } } |
9、現在嘗試訪問你的網頁,應該整體動畫流程都已成形,接下來便可開始微調和優化部分。
See the Pen 利用純SVG+CSS keyframes animation動畫實現手寫毛筆字(書法)效果:“非”字初步預覽 by Yifei He (@hesyifei) on CodePen.
五、微調與優化
1、首先,嘗試不同的keyframes時間百分比以找到你覺得最好的每個筆畫的書寫時間。
2、其次,打開瀏覽器的開發者工具,嘗試定位並修改 .pen
class中 stroke-width
值,看看會不會因為這個值調大了而顯示了更完整的筆畫。如果是可嘗試於CSS中進行修改並查看效果。
3、可嘗試於每個筆序class中(比如 .line-fei-1
)加入一個 !important
的 animation-timing-function
來修改動畫的細節速度,比如可調整為 ease-in
、ease-out
、linear
等等。詳細請參見:CSS animation-timing-function Property
4、加入各個瀏覽器的prefix,比如一個筆畫的動畫可能需要加入以下瀏覽器prefix:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
.line-fei-1 { clip-path: url("#fei-1"); stroke-dasharray: 73; -webkit-animation: draw-fei-1 5s ease; -moz-animation: draw-fei-1 5s ease; -ms-animation: draw-fei-1 5s ease; animation: draw-fei-1 5s ease; } @-webkit-keyframes draw-fei-1 { 0%, 60% { stroke-dashoffset: 73; } 68% { stroke-dashoffset: 0; } } @-moz-keyframes draw-fei-1 { 0%, 60% { stroke-dashoffset: 73; } 68% { stroke-dashoffset: 0; } } @-ms-keyframes draw-fei-1 { 0%, 60% { stroke-dashoffset: 73; } 68% { stroke-dashoffset: 0; } } @-o-keyframes draw-fei-1 { 0%, 60% { stroke-dashoffset: 73; } 68% { stroke-dashoffset: 0; } } @keyframes draw-fei-1 { 0%, 60% { stroke-dashoffset: 73; } 68% { stroke-dashoffset: 0; } } |
4、但很明顯那樣加起來會太過複雜了,所以推薦使用less等其它工具來簡化代碼。以下是“暢想資源”自己用less寫出的一個簡化版本,可供參考:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
@animation-duration: 5s; @animation-timing-function: ease; .pen { fill: none; stroke: rgb(199, 182, 160); stroke-width: 20; stroke-linecap: round; stroke-linejoin: round; stroke-dashoffset: 0; } .do-calligraphy-animation(@name, @strokeDasharray, @startPct, @endPct, @timingFunction: @animation-timing-function) { .p-@{name} { clip-path: url("#@{name}"); stroke-dasharray: @strokeDasharray; .animation(~'draw-@{name}', @animation-duration, @timingFunction); } .keyframes(~'draw-@{name}', { 0%, @{startPct} { stroke-dashoffset: @strokeDasharray; } @{endPct} { stroke-dashoffset: 0; } }); } .do-calligraphy-animation(fei-1, 73, 0%, 20%); .do-calligraphy-animation(fei-2, 25, 20%, 25%); .do-calligraphy-animation(fei-3, 127, 25%, 40%, ease-in); .do-calligraphy-animation(fei-4, 106, 40%, 75%); .do-calligraphy-animation(fei-5, 28, 75%, 82.5%); .do-calligraphy-animation(fei-6, 37, 82.5%, 90%); .do-calligraphy-animation(fei-7, 38, 90%, 100%); |
5、歡迎提供更多意見...
參考資料
Sign on the Dotted Line: Animating Your Own SVG Signature
How to animate handwriting text on the web page using SVG?(特別感謝這一回答,它是網上很少幾個解答了如何在動畫中顯示路徑上的clipPath而非路徑本身的問題,才讓我們可以實現動畫中最重要的一部分)
文中GIF教程動畫使用LICEcap製作,並參考“Optimizing Animated GIFs by Converting to HTML5 Video”轉換為HTML5 MP4視頻。
歷史上的今天
2013年:給WordPress添加評論表情包(38條評論)