文字是網頁中最基本的元素,通常咱們在網頁上都是展現的靜態文字,可是就效果來講,仍是比較枯燥的。文字淡入淡出的動畫效果在項目中很是實用,若是有某些關鍵的文字,能夠經過這種動態的效果來提醒用戶閱讀。html
這個 Demo 是不斷重複地設置文字的大小和透明度,這些英文字母也是我本身利用 HT 的矢量繪製的,總的來講效果仍是不錯的。node
代碼總共一百來行,比較簡單,前面說過個人英文字母是用矢量繪製的,用矢量繪製圖形的好處很是多,好比圖片縮放不會失真,這樣在不一樣的 Retina 顯示屏上我也不須要提供不一樣尺寸的圖片;還有就是用 JSON 的方式來描述矢量,格式比較簡潔等等。json
接下來繪製這些矢量圖片(這裏只拿出第一個 H 進行說明):canvas
{
"width": 10,//設置矢量的寬
"height": 10,//設置矢量的高
"comps": [//矢量圖形的組件Array數組,每一個數組對象爲一個獨立的組件類型,數組的順序爲組件繪製前後順序
{
"type": "text",//文本類型
"text": "H",//文本內容
"color": "rgb(69,69,69)",//文本顏色
"align": "center",//文本在矢量中的對齊方式
"opacity": {//文本透明度
"func": "attr@text.opacity",//設置業務屬性,對文本進行透明度的數據綁定
"value": 1//若是func中的值爲空或者undefined,那麼就直接用這個值
},
"clipDirection": "bottom",//裁切方向爲「從上到下」
"rect": [//指定組件繪製在矢量中的矩形邊界
0,//表明左上角座標x
0,//表明左上角座標y
10,//表明組件的width
10//表明組件的height
]
}]
}
複製代碼
繪製矢量圖形是經過 JSON 格式來書寫的,主要的參數有三個:width、height 以及 comps。這三個參數都必需要寫上,其中 width 爲矢量圖形的寬度,height 爲矢量圖形的高度,comps 裏面是一個 Array 數組,數組中是一個個獨立的對象,能夠對這個對象設置一些預約義參數,也可設置一些可選的參數信息。數組
這裏我將全部的文本信息存儲在一個數組中,方便調用:bash
arr = [
{label: 'H', image: 'symbols/H.json'},
{label: 'T', image: 'symbols/T.json'},
{label: 'f', image: 'symbols/f.json'},
{label: 'o', image: 'symbols/o.json'},
{label: 'r', image: 'symbols/r.json'},
{label: 'W', image: 'symbols/W.json'},
{label: 'e', image: 'symbols/e.json'},
{label: 'b', image: 'symbols/b.json'},
];
複製代碼
第一個 label 對象爲矢量圖形的名稱,第二個 image 對象咱們設置的是 json 格式的圖片,可是實際上能夠爲 img、canvas 對象或圖片 url 或 base64 字符串。app
對象的圖片已經生成,接下來就是建立對象了,這裏英文字母總共 8 個,那麼咱們建立 8 個節點對象:函數
var s = 80;
arr.forEach(function(obj, index) {
var text = obj.label;
name = 't' + text;
window[name] = createNode(obj.image, 100+s*index, 100);
});
function createNode(image, x, y) {//節點對象聲明
var node = new ht.Node();//這個類爲 ht 中定義的節點
node.setSize(0, 0);//設置節點大小
if(image) node.setImage(image);//設置節點圖片
if(x && y) node.setPosition(x, y);//設置節點擺放位置
dm.add(node);//將節點添加進數據容器 datamodel 中
return node;
}
複製代碼
關於上面的 ht.Node 節點的生成,其實這個只是 HT 封裝好的類,這個類上面有不少很方便的 API。而後將這個生成的節點添加進數據容器 dm 中,這個數據容器又是整個拓撲圖 gv 的數據容器。動畫
來看看如何生成這個拓撲圖吧:ui
dm = new ht.DataModel();//數據容器
gv = new ht.graph.GraphView(dm);//拓撲圖 經過 gv.getView() 可得到這個拓撲圖的底層 div
gv.addToDOM();//將 gv 添加進 body 中
複製代碼
實際上 HT 的原理就是在一個 div 中的 canvas 上繪製圖形,也就是說這個 gv 就是一個 canvas。
而後經過 getView 獲取這個 canvas 的底層 div,這樣咱們就能將這個 div 添加到 html 頁面的任何地方了,addToDOM 的定義以下:
addToDOM = function(){
var self = this,
view = self.getView(), //獲取底層div
style = view.style;
document.body.appendChild(view); //將底層div添加到body中
style.left = '0';//由於 HT 默認將組件的position設置爲absolute 因此要設置位置
style.right = '0';
style.top = '0';
style.bottom = '0';
window.addEventListener('resize', function () { self.iv(); }, false);//窗口大小變化觸發事件,調用最外層組件invalidate(即iv)函數進行更新。
}
複製代碼
如今刷新頁面,你會看到一片空白,爲何?由於前面設置節點的大小爲 0 啊,怎麼會顯示,這個 Demo 的效果就是從無到有,又從有到無。那接下來看看如何「從無到有」。
就像我剛剛說過的,要想讓節點顯示,確定是須要設置節點的大小爲咱們肉眼可視的範圍纔會出現,可是個人目的不只是從無到有,也是從小到大,這個可以一鼓作氣麼?感受好像代碼內容簡單,可是代碼量卻不小的一個任務,我定義了一個函數用來將節點從無到有,從小到大:
function setSize(node) {
if(node) {
var s = 80,
size = node.getSize().width;//獲取節點當前的大小中的寬度,由於我知道寬高都是同樣的,因此簡寫了
var sw = s - size;
ht.Default.startAnim({//HT 封裝的動畫函數,內容也是 JSON 格式的對象
duration: 1000,// 動畫週期毫秒數
easing: function(t) { return t*t },//動畫緩動函數
action: function(v, t) {//action函數必須提供,實現動畫過程當中的屬性變化 第一個參數v表明經過easing(t)函數運算後的值,t表明當前動畫進行的進度[0~1],通常屬性變化根據v參數進行
node.setSize(//設置節點的大小 (有一個緩動的過程 經過 sw*v 實現的)
size + sw*v,
size + sw*v
);
}
});
}
}
複製代碼
從大到小,從有到無的過程也跟上面相似,我就不贅述了。
要讓這些字母按照時間的前後順序出現和消失,確定須要用到 setTimeout 方法,要想實現一次的顯示消失是很是容易的,可是我在實現的過程掉到了 setTimeout 的一個陷阱中,只能說本身學藝不精吧。由於咱們須要給不一樣的字母設置不一樣的出現和消失時間,通常比較簡單的方法就是設置一個固定的值,而後乘以對應節點專屬的 index:
function animateIn() {
for(let i = 0; i < arr.length; i++) {
var name = 't' + arr[i];
animateLetterIn(window[name], i);//這個部分設置動畫
}
}
複製代碼
但是若是我直接在 for 循環中設置 setTimeout 的時間爲動態變化的,那麼這個動態變化的值確定是只取 for 循環的最後一個值,因此我將 setTimeout 的方法抽取出來做爲一個單獨的函數:
function animateLetterIn(node, i) {
setTimeout(function() {
setSize(node);
}, i * 200);//這時候這個 i 取的就是節點對應的 i 而不是最後一個值了
if(i === arr.length - 1) {//當節點爲最後一個節點時,設置節點淡出動畫
setTimeout(function() {
animateOut();//節點淡出動畫
}, (arr.length + 3) * 200);
}
}
複製代碼
節點淡出動畫也是相似的方法,只是須要循環調用這些動畫函數,這樣才能作到無限循環字母的大小控制。