今天來一起瞭解一個實現SVG路徑描邊繪製與動畫的輕量級類庫segment,我們從輕鬆上手、使用詳解、資源和案例、源碼解讀等幾個方面進行介紹。
1. 輕鬆上手
html方面添加segment,定義path。
<script src="/dist/segment.min.js"></script><svg> <path id="my-path" ...></svg>
JS方面利用path執行個體化一個segment,然後就可以使用segment的draw方法了。
var myPath = document.getElementById("my-path"), segment = new Segment(myPath);segment.draw("25%", "75% - 10", 1);
2. 使用詳解
2.1 建構函式
Segment建構函式可以接收三個參數。
var segElement=new Segment(path,begin,end);
path: 需要繪製的路徑(DOM元素)。 begin: 路徑開始繪製的位置,選擇性參數,預設值為0。 end: 路徑結束繪製的位置,選擇性參數,預設值為100%。
2.2 draw方法
draw方法是segment的核心方法,可以接受四個參數。
segElement.draw(begin, end, duration, options);
begin: 路徑開始繪製位置,預設值為0。參數類型為string。
數字 百分比 百分比+數字 百分比-數字 end: 路徑結束繪製的位置,預設值為100%,參數類型為string。輸入寫法同begin。 duration: 繪製期間,預設值為0。 options: 繪製參數,預設值為null,參數類型為object類型。具體參數如下。
delay: 延遲時間,預設值為0,單位為s。 easing: 繪製動畫的緩動類型,預設值為linear。 callback: 回呼函數,預設值為null。
draw方法具體案例如下。
function cubicIn(t) { return t * t * t;}function done() { alert("Done!");}segment.draw("25%", "75% - 10", 1, {delay: 0.5, easing: cubicIn, callback: done});
3. 資源和案例 Codrop的Animating an SVG Menu Icon with Segment 官方案例 官方教程Animating SVG path segments
4. 源碼解讀
通過源碼閱讀,學習類庫的開發,svg動畫的具體實現。
/** * segment - A little JavaScript class (without dependencies) to draw and animate SVG path strokes * @version v0.0.4 * @link https://github.com/lmgonzalves/segment * @license MIT */function Segment(path, begin, end) { this.path = path; this.length = path.getTotalLength(); this.path.style.strokeDashoffset = this.length * 2; this.begin = typeof begin !== 'undefined' ? this.valueOf(begin) : 0; this.end = typeof end !== 'undefined' ? this.valueOf(end) : this.length; this.timer = null; this.draw(this.begin, this.end);}Segment.prototype = { draw : function(begin, end, duration, options){ if(duration){ var delay = options && options.hasOwnProperty('delay') ? parseFloat(options.delay) * 1000 : 0, easing = options && options.hasOwnProperty('easing') ? options.easing : null, callback = options && options.hasOwnProperty('callback') ? options.callback : null, that = this; this.stop(); if(delay) { delete options.delay; this.timer = setTimeout(function () { that.draw(begin, end, duration, options); }, delay); return this.timer; } var startTime = new Date(), rate = 1000/60, initBegin = this.begin, initEnd = this.end, finalBegin = this.valueOf(begin), finalEnd = this.valueOf(end); (function calc(){ var now = new Date(), elapsed = (now-startTime)/1000, time = (elapsed/parseFloat(duration)), t = time; if(typeof easing === 'function') { t = easing(t); } if(time > 1){ that.stop(); t = 1; }else{ that.timer = setTimeout(calc, rate); } that.begin = initBegin + (finalBegin - initBegin) * t; that.end = initEnd + (finalEnd - initEnd) * t; if(that.begin < 0) { that.begin = 0; } if(that.end > that.length) { that.end = that.length; } if(that.begin < that.end) { that.draw(that.begin, that.end); }else{ that.draw(that.begin + (that.end - that.begin), that.end - (that.end - that.begin)); } if(time > 1 && typeof callback === 'function'){ return callback.call(that.context); } })(); }else{ this.path.style.strokeDasharray = this.strokeDasharray(begin, end); } }, strokeDasharray : function(begin, end){ this.begin = this.valueOf(begin); this.end = this.valueOf(end); return [this.length, this.length + this.begin, this.end - this.begin].join(' '); }, valueOf: function(input){ var val = parseFloat(input); if(typeof input === 'string' || input instanceof String){ if(~input.indexOf('%')){ var arr; if(~input.indexOf('+')){ arr = input.split('+'); val = this.percent(arr[0]) + parseFloat(arr[1]); }else if(~input.indexOf('-')){ arr = input.split('-'); val = this.percent(arr[0]) - parseFloat(arr[1]); }else{ val = this.percent(input); } } } return val; }, stop : function(){ clearTimeout(this.timer); this.timer = null; }, percent : function(value){ return parseFloat(value) / 100 * this.length; }};
5. 聲明
本文首發於極客頭條。愛前端,樂分享。FedFun希望與您共同進步。
歡迎任何形式的轉載,煩請註明裝載,保留本段文字。
獨立部落格http://whqet.github.io
新浪微博http://weibo.com/FedFun
極客頭條