您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“HTML5中怎么用Canvas實(shí)現(xiàn)文字動(dòng)畫(huà)特效”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
代碼總共一百來(lái)行,比較簡(jiǎn)單,前面說(shuō)過(guò)我的英文字母是用矢量繪制的,用矢量繪制圖形的好處非常多,比如圖片縮放不會(huì)失真,這樣在不同的Retina顯示屏上我也不需要提供不同尺寸的圖片;還有就是用JSON的方式來(lái)描述矢量,格式比較簡(jiǎn)潔等等。
矢量圖片
接下來(lái)繪制這些矢量圖片(這里只拿出第一個(gè)H進(jìn)行說(shuō)明):
{"width":10,//設(shè)置矢量的寬
"height":10,//設(shè)置矢量的高
"comps":[//矢量圖形的組件Array數(shù)組,每個(gè)數(shù)組對(duì)象為一個(gè)獨(dú)立的組件類型,數(shù)組的順序?yàn)榻M件繪制先后順序{"type":"text",//文本類型
"text":"H",//文本內(nèi)容
"color":"rgb(69,69,69)",//文本顏色
"align":"center",//文本在矢量中的對(duì)齊方式
"opacity":{//文本透明度
"func":"attr@text.opacity",//設(shè)置業(yè)務(wù)屬性,對(duì)文本進(jìn)行透明度的數(shù)據(jù)綁定
"value":1//如果func中的值為空或者undefined,那么就直接用這個(gè)值},"clipDirection":"bottom",//裁切方向?yàn)椤皬纳系较隆?/p>
"rect":[//指定組件繪制在矢量中的矩形邊界
0,//代表左上角坐標(biāo)x
0,//代表左上角坐標(biāo)y
10,//代表組件的width
10//代表組件的height]
}]
}
繪制矢量圖形是通過(guò)JSON格式來(lái)書(shū)寫(xiě)的,主要的參數(shù)有三個(gè):width、height以及comps。這三個(gè)參數(shù)都必須要寫(xiě)上,其中width為矢量圖形的寬度,height為矢量圖形的高度,comps里面是一個(gè)Array數(shù)組,數(shù)組中是一個(gè)個(gè)獨(dú)立的對(duì)象,可以對(duì)這個(gè)對(duì)象設(shè)置一些預(yù)定義參數(shù),也可設(shè)置一些可選的參數(shù)信息。
這里我將所有的文本信息存儲(chǔ)在一個(gè)數(shù)組中,方便調(diào)用:
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'},
];
第一個(gè)label對(duì)象為矢量圖形的名稱,第二個(gè)image對(duì)象我們?cè)O(shè)置的是json格式的圖片,但是實(shí)際上可以為img、canvas對(duì)象或圖片url或base64字符串。
創(chuàng)建節(jié)點(diǎn)對(duì)象
對(duì)象的圖片已經(jīng)生成,接下來(lái)就是創(chuàng)建對(duì)象了,這里英文字母總共8個(gè),那么我們創(chuàng)建8個(gè)節(jié)點(diǎn)對(duì)象:
vars=80;
arr.forEach(function(obj,index){
vartext=obj.label;
name='t'+text;
window[name]=createNode(obj.image,100+s*index,100);
});
functioncreateNode(image,x,y){//節(jié)點(diǎn)對(duì)象聲明
varnode=newht.Node();//這個(gè)類為ht中定義的節(jié)點(diǎn)
node.setSize(0,0);//設(shè)置節(jié)點(diǎn)大小
if(image)node.setImage(image);//設(shè)置節(jié)點(diǎn)圖片
if(x&&y)node.setPosition(x,y);//設(shè)置節(jié)點(diǎn)擺放位置
dm.add(node);//將節(jié)點(diǎn)添加進(jìn)數(shù)據(jù)容器datamodel中
returnnode;
}
關(guān)于上面的ht.Node節(jié)點(diǎn)的生成,其實(shí)這個(gè)只是HT封裝好的類,這個(gè)類上面有很多很方便的API。然后將這個(gè)生成的節(jié)點(diǎn)添加進(jìn)數(shù)據(jù)容器dm中,這個(gè)數(shù)據(jù)容器又是整個(gè)拓?fù)鋱Dgv的數(shù)據(jù)容器。
拓?fù)鋱D生成
來(lái)看看如何生成這個(gè)拓?fù)鋱D吧:
dm=newht.DataModel();//數(shù)據(jù)容器gv=newht.graph.GraphView(dm);//拓?fù)鋱D通過(guò)gv.getView()可獲得這個(gè)拓?fù)鋱D的底層pgv.addToDOM();//將gv添加進(jìn)body中
實(shí)際上HT的原理就是在一個(gè)p中的canvas上繪制圖形,也就是說(shuō)這個(gè)gv就是一個(gè)canvas。
然后通過(guò)getView獲取這個(gè)canvas的底層p,這樣我們就能將這個(gè)p添加到html頁(yè)面的任何地方了,addToDOM的定義如下:
addToDOM=function(){
varself=this,
view=self.getView(),//獲取底層p
style=view.style;
document.body.appendChild(view);//將底層p添加到body中
style.left='0';//因?yàn)镠T默認(rèn)將組件的position設(shè)置為absolute所以要設(shè)置位置
style.right='0';
style.top='0';
style.bottom='0';
window.addEventListener('resize',function(){self.iv();},false);//窗口大小變化觸發(fā)事件,調(diào)用最外層組件invalidate(即iv)函數(shù)進(jìn)行更新。}
現(xiàn)在刷新頁(yè)面,你會(huì)看到一片空白,為什么?因?yàn)榍懊嬖O(shè)置節(jié)點(diǎn)的大小為0啊,怎么會(huì)顯示,這個(gè)Demo的效果就是從無(wú)到有,又從有到無(wú)。那接下來(lái)看看如何“從無(wú)到有”。
文本動(dòng)畫(huà)
就像我剛剛說(shuō)過(guò)的,要想讓節(jié)點(diǎn)顯示,肯定是需要設(shè)置節(jié)點(diǎn)的大小為我們?nèi)庋劭梢暤姆秶艜?huì)出現(xiàn),但是我的目的不僅是從無(wú)到有,也是從小到大,這個(gè)能夠一氣呵成么?感覺(jué)好像代碼內(nèi)容簡(jiǎn)單,但是代碼量卻不小的一個(gè)任務(wù),我定義了一個(gè)函數(shù)用來(lái)將節(jié)點(diǎn)從無(wú)到有,從小到大:
functionsetSize(node){
if(node){
vars=80,
size=node.getSize().width;//獲取節(jié)點(diǎn)當(dāng)前的大小中的寬度,因?yàn)槲抑缹捀叨际且粯拥?,所以?jiǎn)寫(xiě)了
varsw=s-size;
ht.Default.startAnim({//HT封裝的動(dòng)畫(huà)函數(shù),內(nèi)容也是JSON格式的對(duì)象
duration:1000,//動(dòng)畫(huà)周期毫秒數(shù)
easing:function(t){returnt*t},//動(dòng)畫(huà)緩動(dòng)函數(shù)
action:function(v,t){//action函數(shù)必須提供,實(shí)現(xiàn)動(dòng)畫(huà)過(guò)程中的屬性變化第一個(gè)參數(shù)v代表通過(guò)easing(t)函數(shù)運(yùn)算后的值,t代表當(dāng)前動(dòng)畫(huà)進(jìn)行的進(jìn)度[0~1],一般屬性變化根據(jù)v參數(shù)進(jìn)行
node.setSize(//設(shè)置節(jié)點(diǎn)的大小(有一個(gè)緩動(dòng)的過(guò)程通過(guò)sw*v實(shí)現(xiàn)的)
size+sw*v,
size+sw*v
);
}
});
}
}
從大到小,從有到無(wú)的過(guò)程也跟上面類似,我就不贅述了。
要讓這些字母按照時(shí)間的先后順序出現(xiàn)和消失,肯定需要用到setTimeout方法,要想實(shí)現(xiàn)一次的顯示消失是非常容易的,但是我在實(shí)現(xiàn)的過(guò)程掉到了setTimeout的一個(gè)陷阱中,只能說(shuō)自己學(xué)藝不精吧。因?yàn)槲覀冃枰o不同的字母設(shè)置不同的出現(xiàn)和消失時(shí)間,一般比較簡(jiǎn)單的方法就是設(shè)置一個(gè)固定的值,然后乘以對(duì)應(yīng)節(jié)點(diǎn)專屬的index:
functionanimateIn(){
for(leti=0;i<arr.length;i++){
varname='t'+arr[i];
animateLetterIn(window[name],i);//這個(gè)部分設(shè)置動(dòng)畫(huà)
}
}
可是如果我直接在for循環(huán)中設(shè)置setTimeout的時(shí)間為動(dòng)態(tài)變化的,那么這個(gè)動(dòng)態(tài)變化的值肯定是只取for循環(huán)的最后一個(gè)值,所以我將setTimeout的方法抽取出來(lái)作為一個(gè)單獨(dú)的函數(shù):
functionanimateLetterIn(node,i){
setTimeout(function(){
setSize(node);
},i*200);//這時(shí)候這個(gè)i取的就是節(jié)點(diǎn)對(duì)應(yīng)的i而不是最后一個(gè)值了
if(i===arr.length-1){//當(dāng)節(jié)點(diǎn)為最后一個(gè)節(jié)點(diǎn)時(shí),設(shè)置節(jié)點(diǎn)淡出動(dòng)畫(huà)
setTimeout(function(){
animateOut();//節(jié)點(diǎn)淡出動(dòng)畫(huà)
},(arr.length+3)*200);
}
}
“HTML5中怎么用Canvas實(shí)現(xiàn)文字動(dòng)畫(huà)特效”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。