基於 Canvas 的 HTML5 文字動畫特效
前言
文字是網頁中最基本的元素,一般我們在網頁上都是展示的靜態文字,但是就效果來說,還是比較枯燥的。文字淡入淡出的動畫效果在專案中非常實用,如果有某些關鍵的文字,可以通過這種動態的效果來提醒使用者閱讀。
動態效果圖:
http://www.hightopo.com/demo/GraphAnimation/index.html
這個 Demo 是不斷重複地設定文字的大小和透明度,這些英文字母也是我自己利用 HT 的向量繪製的,總的來說效果還是不錯的。
程式碼實現
程式碼總共一百來行,比較簡單,前面說過我的英文字母是用向量繪製的,用向量繪製圖形的好處非常多,比如圖片縮放不會失真,這樣在不同的 Retina 螢幕上我也不需要提供不同尺寸的圖片;還有就是用 JSON 的方式來描述向量,格式比較簡潔等等。
向量圖片
接下來繪製這些向量圖片(這裡只拿出第一個 H 進行說明):
{
"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 陣列,陣列中是一個個獨立的物件,可以對這個物件設定一些預定義引數,也可設定一些可選的引數資訊。
這裡我將所有的文字資訊儲存在一個陣列中,方便呼叫:
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 字串。
建立節點物件
物件的圖片已經生成,接下來就是建立物件了,這裡英文字母總共 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 的資料容器。
拓撲圖生成
來看看如何生成這個拓撲圖吧:
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);
}
}
節點淡出動畫也是類似的方法,只是需要迴圈呼叫這些動畫函式,這樣才能做到無限迴圈字母的大小控制。
相關文章
- 基於 HTML5 Canvas 實現文字動畫特效HTMLCanvas動畫特效
- 基於 HTML5 Canvas 實現的文字動畫特效HTMLCanvas動畫特效
- 16個非常有趣的HTML5 Canvas動畫特效集合HTMLCanvas動畫特效
- 基於canvas的骨骼動畫Canvas動畫
- canvas動畫特效 之 星空Canvas動畫特效
- Html5 Canvas動畫基礎(碰撞檢測)HTMLCanvas動畫
- 基於 HTML5 Canvas 的可互動旋鈕元件HTMLCanvas元件
- Html5 canvas創意特效合集HTMLCanvas特效
- 基於 Canvas 的 HTML5 互動式地鐵線路圖CanvasHTML
- 基於 HTML5 Canvas 的工控機櫃 U 位動態管理HTMLCanvas
- 基於 Canvas 的 HTML5 工控機櫃 U 位動態管理CanvasHTML
- 超酷!!HTML5 Canvas 水流樣式 Loading 動畫HTMLCanvas動畫
- 基於 HTML5 Canvas 的電信機櫃 U 位動態管理HTMLCanvas
- 基於 HTML5 Canvas 的元素週期表展示HTMLCanvas
- 基於 HTML5 Canvas 的樓宇自控系統HTMLCanvas
- 基於 HTML5 Canvas 的元素週期表的展示HTMLCanvas
- HTML5 Canvas 超逼真煙花綻放動畫HTMLCanvas動畫
- HTML5+Canvas漂亮的3D煙花動畫生日特效,節日特效,煙花HTMLCanvas3D動畫特效
- 用HTML5的canvas畫太陽系HTMLCanvas
- 基於 HTML5 Canvas 的拓撲元件 ToolTip 應用HTMLCanvas元件
- jquery文字動畫特效外掛分享animatext.js文件jQuery動畫特效JS
- 基於 HTML5 實現的簡單雲動畫和景物描述HTML動畫
- 5分鐘學會製作 CSS 波浪文字動畫特效CSS動畫特效
- canvas動畫教程-2 基礎設施Canvas動畫
- 基於 HTML5 Canvas 的 3D 熱力雲圖效果HTMLCanvas3D
- canvas動畫心得Canvas動畫
- canvas水球動畫Canvas動畫
- 【轉】5分鐘學會製作 CSS 波浪文字動畫特效CSS動畫特效
- 基於 HTML5 Canvas 電信網路拓撲圖的快速搭建HTMLCanvas
- canvas簡單的畫布動畫 - KaiqisanCanvas動畫AI
- html5中canvas元素建立畫布介紹HTMLCanvas
- canvas繪製動畫的技巧Canvas動畫
- 基於HTML5的移動Web應用HTMLWeb
- loading動畫的效能優化-摒棄Canvas,擁抱CSS3-實現點選特效動畫優化CanvasCSSS3特效
- JQuery3:動畫和特效jQuery動畫特效
- 【CSS】圖片動畫特效(相框)CSS動畫特效
- jquery計數器動畫特效jQuery動畫特效
- canvas動畫教程-1 引言Canvas動畫