簡單的SVG線條動畫

我啥時候說啦jj發表於2017-12-27

[TOC]

Demo專案下載

看到網頁中那種有如寫字般的動畫,覺得挺好玩的,就找了下製作方法,也比較簡單,在此記錄一下; 先上幾張圖看看:

簡單的線條動畫

ps4

用到的屬性

stroke 定義邊框顏色值; stroke-width 定義描邊寬度; stroke-dashoarray 前一個數值表示dash,後一個數字表示gap長度(只寫單個值表示dash/gap尺寸一致),往復迴圈; stroke-dashoffset 虛線開始時的偏移長度,正數則從路徑起始點向前偏移,負數則向後偏移;

原理

  1. 定義 stroke-dashoarray 屬性,使svg圖案的 dash 和 gap 長度大於等於最終圖案長度值(記為len);
  2. 將其往前偏移len,使dash部分初始隱藏,只顯示 gap , gap 又是空白的,所以初始時頁面無任何東西;
  3. 定義動畫,不斷改變 stroke-dashoffset 的值直至為0,就出現了動畫;

繪製svg圖案

主要使用到 path 標籤,具體可以看 這裡 ; 複雜點的圖案就不建議手動書寫,可採用第三方軟體,匯出成svg檔案,刪除無用程式碼即可,如: Inkscape 線上編輯

動畫實現

可通過css或js來控制動畫的實現,css比較簡單,但圖案的長度等引數不易掌控;

CSS實現

<style>
    path {
        stroke-dasharray: 610;//實線-間隔長度都是610(大於所畫長度)
        stroke-dashoffset: 610;//往前偏移610(超過圖形長度),則初始顯示為空白
        animation: dash 5s linear;//新增動畫,使偏移逐漸變為0,以顯示完整圖案
        animation-fill-mode: forwards;//動畫完成後保持不變
    }

    // 定義css動畫,@keyframes yourName
    @keyframes dash {
        to {
            stroke-dashoffset: 0;
        }
    }
</style>
複製程式碼

js控制動畫

初始化相關屬性

//程式碼獲取長度並設定動畫相關屬性
var path = document.querySelector('path');
var len = path.getTotalLength();
console.log("總長度 : " + len);

//定義實線和空白區域長度
path.style.strokeDasharray = len + 10;
//定義初始dash部分相對起始點的偏移量,正數表示往前便宜
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:定時重新整理重繪

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比較依賴系統重新整理率,若硬體效能問題導致fps下降嚴重,則可能出現較嚴重卡頓現象

最終效果

參考

W3C SVG MDN-SVG Painting: Filling, Stroking and Marker Symbols Animated line drawing in SVG 用css定義svg的樣式和動畫 SVG SMIL animation動畫詳解

相關文章