[TOC]
看到網(wǎng)頁(yè)中那種有如寫字般的動(dòng)畫,覺(jué)得挺好玩的,就找了下制作方法,也比較簡(jiǎn)單,在此記錄一下;
先上幾張圖看看:
用到的屬性
stroke 定義邊框顏色值;
stroke-width 定義描邊寬度;
stroke-dashoarray 前一個(gè)數(shù)值表示dash,后一個(gè)數(shù)字表示gap長(zhǎng)度(只寫單個(gè)值表示dash/gap尺寸一致),往復(fù)循環(huán);
stroke-dashoffset 虛線開始時(shí)的偏移長(zhǎng)度,正數(shù)則從路徑起始點(diǎn)向前偏移,負(fù)數(shù)則向后偏移;
原理
- 定義
stroke-dashoarray
屬性,使svg圖案的 dash 和 gap 長(zhǎng)度大于等于最終圖案長(zhǎng)度值(記為len); - 將其往前偏移len,使dash部分初始隱藏,只顯示 gap , gap 又是空白的,所以初始時(shí)頁(yè)面無(wú)任何東西;
- 定義動(dòng)畫,不斷改變
stroke-dashoffset
的值直至為0,就出現(xiàn)了動(dòng)畫;
繪制svg圖案
主要使用到 path 標(biāo)簽,具體可以看 這里 ;
復(fù)雜點(diǎn)的圖案就不建議手動(dòng)書寫,可采用第三方軟件,導(dǎo)出成svg文件,刪除無(wú)用代碼即可,如:
Inkscape
在線編輯
動(dòng)畫實(shí)現(xiàn)
可通過(guò)css或js來(lái)控制動(dòng)畫的實(shí)現(xiàn),css比較簡(jiǎn)單,但圖案的長(zhǎng)度等參數(shù)不易掌控;
CSS實(shí)現(xiàn)
<style>
path {
stroke-dasharray: 610;//實(shí)線-間隔長(zhǎng)度都是610(大于所畫長(zhǎng)度)
stroke-dashoffset: 610;//往前偏移610(超過(guò)圖形長(zhǎng)度),則初始顯示為空白
animation: dash 5s linear;//添加動(dòng)畫,使偏移逐漸變?yōu)?,以顯示完整圖案
animation-fill-mode: forwards;//動(dòng)畫完成后保持不變
}
// 定義css動(dòng)畫,@keyframes yourName
@keyframes dash {
to {
stroke-dashoffset: 0;
}
}
</style>
js控制動(dòng)畫
初始化相關(guān)屬性
//代碼獲取長(zhǎng)度并設(shè)置動(dòng)畫相關(guān)屬性
var path = document.querySelector('path');
var len = path.getTotalLength();
console.log("總長(zhǎng)度 : " + len);
//定義實(shí)線和空白區(qū)域長(zhǎng)度
path.style.strokeDasharray = len + 10;
//定義初始dash部分相對(duì)起始點(diǎn)的偏移量,正數(shù)表示往前便宜
path.style.strokeDashoffset = len + 10;
方式1:使用transition
// 方式1:參考文章: https://jakearchibald.com/2013/animated-line-drawing-svg/
path.style.transition = path.style.WebkitTransition =
'none';
// Trigger a layout so styles are calculated & the browser
// picks up the starting position before animating
path.getBoundingClientRect();
path.style.transition = path.style.WebkitTransition =
'stroke-dashoffset 5s ease-in-out';
path.style.strokeDashoffset = '0';
方式2:定時(shí)刷新重繪
var initial_ts = new Date().getTime();
var duration = 5000;
var draw = function () {
var progress = (Date.now() - initial_ts) / duration;
if (progress < 1) {
path.style.strokeDashoffset = Math.floor(len * (1 - progress));
setTimeout(draw, 50);
}
};
draw();
方式3:使用requestAnimationFrame
var initial_ts = new Date().getTime();
var duration = 5000;
var handle = 0;
var animate = function () {
var progress = (Date.now() - initial_ts) / duration;
if (progress >= 1) {
window.cancelAnimationFrame(handle);
} else {
path.style.strokeDashoffset = Math.floor(len * (1 - progress));
handle = window.requestAnimationFrame(animate);
}
};
animate();
方式3比較依賴系統(tǒng)刷新率,若硬件性能問(wèn)題導(dǎo)致fps下降嚴(yán)重,則可能出現(xiàn)較嚴(yán)重卡頓現(xiàn)象
參考
W3C SVG
MDN-SVG
Painting: Filling, Stroking and Marker Symbols
Animated line drawing in SVG
用css定義svg的樣式和動(dòng)畫
SVG SMIL animation動(dòng)畫詳解