一直以來(lái)都覺(jué)得程序員的審美不行(包括我自己),但是后來(lái)接觸了不少的程序員,感覺(jué)不是審美不行,而是,懶。當(dāng)然一般來(lái)講,很多事情就應(yīng)該是美工來(lái)做的。先看這個(gè)HTML5/canvas時(shí)鐘,界面很簡(jiǎn)單,僅僅是幾個(gè)純色的圓環(huán),但是對(duì)于初學(xué)者來(lái)說(shuō),實(shí)現(xiàn)起來(lái)還是有點(diǎn)難度的,這個(gè)時(shí)間也是獲取的本地時(shí)間,對(duì)于基礎(chǔ)的javascript水平需要非常的扎實(shí),而且對(duì)于canvas的屬性,也需要很熟悉,主要還是javascript的邏輯要清晰,還有對(duì)于一些小細(xì)節(jié)的處理很重要,javascript算法倒是不多,想要更多HTML5/javascript特效游戲的朋友可以多關(guān)注我以前發(fā)的文章!以下附上源碼!
如果有正在學(xué)習(xí)前端javascript的伙伴,不知道怎么學(xué)習(xí),或者該學(xué)些什么才能找到工作的可以一起來(lái)我們的頭條前端群570946165,一整套前端學(xué)習(xí)路線(xiàn)及系統(tǒng)學(xué)習(xí)資料已上傳到群文件!
代碼過(guò)長(zhǎng)需要文檔版源碼來(lái)我的前端群570946165,源碼已經(jīng)上傳了!
5近兩年在國(guó)內(nèi)持續(xù)發(fā)酵,使得交互(interaction)這一概念從網(wǎng)站設(shè)計(jì)逐漸延伸到H5上。
就像魚(yú)離不開(kāi)水,H5離開(kāi)了交互,便失去了HTML5語(yǔ)言所賦予頁(yè)面形態(tài)的價(jià)值。說(shuō)白了,如果H5弱化了交互,它充其量只是一個(gè)移動(dòng)頁(yè)面的滑動(dòng)PPT,根本談不上是H5。
“交互功能就像橡皮泥,只要發(fā)揮想象,它就能捏成各種形狀。”這是iH5.cn某位不愿意露臉的專(zhuān)業(yè)設(shè)計(jì)師原話(huà)。只要發(fā)揮想象,即便是同一個(gè)交互功能,也能延伸出各式各樣的戲法。
接下來(lái)以H5頁(yè)面制作工具——iH5.cn為例,選用最常用的時(shí)間軸功能,一步步深入探究它能延伸出的各種戲法。
1.先別急著動(dòng)手,時(shí)間軸究竟為何物?
如果對(duì)時(shí)間軸的概念不清晰,說(shuō)再多也是白費(fèi),我們先來(lái)科普一下時(shí)間軸。
如果在初中電腦課上有學(xué)過(guò)Flash制作小汽車(chē)運(yùn)動(dòng)的朋友,看到時(shí)間軸的界面時(shí)應(yīng)該會(huì)感到很熟悉。沒(méi)錯(cuò),時(shí)間軸的概念類(lèi)似于Flash動(dòng)畫(huà)制作,通過(guò)關(guān)鍵幀控制對(duì)象在規(guī)定時(shí)間內(nèi)的運(yùn)動(dòng)軌跡。
想用時(shí)間軸,請(qǐng)務(wù)必記住以下操作邏輯順序:時(shí)間軸——對(duì)象——軌跡——關(guān)鍵幀——修改關(guān)鍵幀屬性。
那么,時(shí)間軸最常見(jiàn)、最簡(jiǎn)單粗暴的應(yīng)用是啥呢?
2.規(guī)律性的幾何運(yùn)動(dòng)
只要打開(kāi)時(shí)間軸的循環(huán)播放功能,它就變成了無(wú)限循環(huán)的時(shí)間單元,所以我們能用時(shí)間軸延伸出很多規(guī)律性的運(yùn)動(dòng)形態(tài),打個(gè)比方——
(1)線(xiàn)性運(yùn)動(dòng)
就比如上面這個(gè)奔跑的男人,純粹是單向線(xiàn)性往返運(yùn)動(dòng),它的原理跟上面提到的用Flash做小汽車(chē)運(yùn)動(dòng)是一樣的,我們只需在時(shí)間軸上,用多個(gè)關(guān)鍵幀控制這個(gè)男人的X坐標(biāo)就能實(shí)現(xiàn)了——
說(shuō)到這里,要跟大家分享一個(gè)小技巧。大家注意到這個(gè)男人其實(shí)是在做往返運(yùn)動(dòng),前進(jìn)跟倒退的軌跡是剛好相反的。
因此我們?cè)谶@類(lèi)往返運(yùn)動(dòng)制作時(shí),只需做好前進(jìn)的軌跡,然后在時(shí)間軸下插入一個(gè)“結(jié)束——時(shí)間軸反向播放”的事件,這樣能減少很多工序,又能對(duì)稱(chēng)兩個(gè)運(yùn)動(dòng)軌跡。
(2)圓周運(yùn)動(dòng)
跟線(xiàn)性運(yùn)動(dòng)相似,圓周運(yùn)動(dòng)只不過(guò)是在關(guān)鍵幀上調(diào)整素材的旋轉(zhuǎn)角度,這是換湯不換藥的,最常見(jiàn)的應(yīng)用就是模仿現(xiàn)實(shí)生活中的手表/時(shí)鐘,讓秒針、分針做周而復(fù)始的圓周運(yùn)動(dòng)。
假如把線(xiàn)性運(yùn)動(dòng)跟圓周運(yùn)動(dòng)同時(shí)放在同一個(gè)時(shí)間軸下,那么恭喜你,一個(gè)簡(jiǎn)單粗暴的時(shí)間軸動(dòng)畫(huà)完成了——
說(shuō)到這里,不禁想吐槽一下...為什么圓周運(yùn)動(dòng)式的玩法這么獨(dú)特!這么好玩!怎么這么少設(shè)計(jì)師用?
它明明可以產(chǎn)生很多交互上的化學(xué)反應(yīng)!無(wú)論是預(yù)加載的Loading頁(yè),還是過(guò)渡頁(yè),圓周運(yùn)動(dòng)式的時(shí)間軸動(dòng)畫(huà)都能給用戶(hù)一種獨(dú)特的心理預(yù)期,比如這種——
希望往后能看到這類(lèi)時(shí)間軸應(yīng)用的化學(xué)反應(yīng)吧,咳咳,有點(diǎn)跑偏了,我們繼續(xù)...
3.不存在規(guī)律的運(yùn)動(dòng)
其實(shí)說(shuō)不存在規(guī)律的運(yùn)動(dòng)有點(diǎn)籠統(tǒng),其實(shí)說(shuō)成仿真式視頻效果會(huì)比較合適,因?yàn)檫@類(lèi)往往會(huì)讓你分不清它到底是時(shí)間軸動(dòng)畫(huà),還是視頻。
比如最近iH5.cn上那位專(zhuān)攻時(shí)間軸動(dòng)畫(huà)的設(shè)計(jì)師小牙,他不久前的《門(mén)窗都關(guān)了,你就給我看這個(gè)?》H5——
效果就跟用AE做的動(dòng)畫(huà)視頻如出一轍,特別是那個(gè)全屏振動(dòng)效果,這完全媲美AE上的wiggle(a,b)振動(dòng)效果!只不過(guò),小牙用的只是一個(gè)簡(jiǎn)單的“全屏振動(dòng)”事件,就將這個(gè)效果復(fù)現(xiàn)了。
在這整套時(shí)間軸方案上看,設(shè)計(jì)師小牙讓我們看到了時(shí)間軸的更多可能,用時(shí)間軸模仿動(dòng)畫(huà)視頻,未嘗不是一個(gè)很好的應(yīng)用形式。
時(shí)間軸還能做什么?
4.用時(shí)間軸做高級(jí)動(dòng)效
時(shí)間軸動(dòng)效的原理和原生的動(dòng)效組件相似,都是通過(guò)在單位時(shí)間內(nèi),改變?cè)氐?strong>位置、大小、透明度、旋轉(zhuǎn)角度等促成相應(yīng)的動(dòng)效效果。
可以是單位時(shí)間內(nèi)控制單一屬性,也可以是控制多個(gè)屬性。
控制多個(gè)屬性時(shí),實(shí)現(xiàn)的動(dòng)效效果更為驚艷!比如——
橡皮糖式滑動(dòng)效果(控制高度、Y坐標(biāo))
重影效果(控制透明度、旋轉(zhuǎn)角度)
對(duì)折翻轉(zhuǎn)效果(繞X坐標(biāo)旋轉(zhuǎn))
視差效果(控制剪切屬性)
360度物體展示(控制旋轉(zhuǎn)角度、視距)
5.用時(shí)間軸做輔助
時(shí)間軸的靈活度很高,除了像上面提到的實(shí)現(xiàn)各種高大上交互,還可以作為輔助功能使用。此時(shí)可以將時(shí)間軸理解成導(dǎo)火線(xiàn),用來(lái)引爆交互這顆重磅炸彈。
那么,它能“引爆”哪些交互?
用時(shí)間軸的循環(huán)播放控制頁(yè)面自動(dòng)翻頁(yè)
時(shí)間軸用事件連接計(jì)數(shù)器,做成倒計(jì)時(shí)
時(shí)間軸用事件連接動(dòng)效組件,配合動(dòng)效的延時(shí)觸發(fā),讓動(dòng)效的銜接更自然
時(shí)間軸獲取當(dāng)前事件,制作按下1秒等敏捷類(lèi)小游戲
當(dāng)然時(shí)間軸的輔助性應(yīng)用遠(yuǎn)不止于此,上面只是拋磚引玉,還有更多有趣&實(shí)用的技法,還需靠大家去發(fā)掘。
功能就放在那兒,看似是死的;但只要懂的思考,它就能活起來(lái),甚至能讓你的H5作品迸發(fā)出更多的光彩。
現(xiàn)在,你能聯(lián)想出哪個(gè)功能的延伸應(yīng)用了嗎?
JavaScript里,我們已經(jīng)會(huì)使用一些原生提供的方法來(lái)實(shí)現(xiàn)需要延時(shí)執(zhí)行的操作代碼,比如很多在線(xiàn)時(shí)鐘的制作,圖片輪播的實(shí)現(xiàn),還有一些廣告彈窗,但凡可以自動(dòng)執(zhí)行的東西,都是可以和定時(shí)器有關(guān)的。今天就來(lái)和大家分享一下,關(guān)于我們?cè)贘avaScript里經(jīng)常會(huì)使用到的定時(shí)器方法
在JavaScript里,我們要學(xué)習(xí)四個(gè)定時(shí)器的使用方法,setTiemout、setInterval、setImmediate、requestAnimationFrame,一起來(lái)看看吧!
JavaScript中提供了一些原生的函數(shù)方法來(lái)實(shí)現(xiàn)延時(shí)去執(zhí)行某一段代碼,這個(gè)就是定時(shí)器
下面我們來(lái)認(rèn)識(shí)一下這些定時(shí)器
setTimeout:
設(shè)置一個(gè)定時(shí)器,在定時(shí)器到期后執(zhí)行一次函數(shù)或代碼段
var timeoutId=window.setTimeout(func[, delay,param1,...]);
var timeoutId=window.setTimeout(code[, delay]);
上面用到的關(guān)鍵詞名稱(chēng)的意義:
timeoutId: 定時(shí)器ID
func: 延遲后執(zhí)行的函數(shù)
code: 延遲后執(zhí)行的代碼字符串,不推薦使用原理類(lèi)似eval()
delay: 延遲的時(shí)間(單位:毫秒),默認(rèn)值為0
param1: 向延遲函數(shù)傳遞而外的參數(shù),IE9以上支持
setInterval:
以固定的時(shí)間間隔重復(fù)調(diào)用一個(gè)函數(shù)或者代碼段
var intervalId=window.setInterval(func, delay[, param1,...]);
var intervalId=window.setInterval(code, delay);
intervalId: 重復(fù)操作的ID
func: 延遲調(diào)用的函數(shù)
code: 代碼段
delay: 延遲時(shí)間,沒(méi)有默認(rèn)值
setImmediate:
在瀏覽器完全結(jié)束當(dāng)前運(yùn)行的操作之后立即執(zhí)行指定的函數(shù)(僅IE10和Node 0.10+中有實(shí)現(xiàn)),類(lèi)似setTimeout(func, 0)
var immediateId=setImmediate(func[, param1, param2, ...]);
var immediateId=setImmediate(func);
immediateId: 定時(shí)器ID
func: 回調(diào)
requestAnimationFrame:
專(zhuān)門(mén)為實(shí)現(xiàn)高性能的幀動(dòng)畫(huà)而設(shè)計(jì)的API,但是不能指定延遲時(shí)間,而是根據(jù)瀏覽器的刷新頻率而定(幀)
var requestId=window.requestAnimationFrame(func);
func: 回調(diào)
基本用法
// 下面代碼執(zhí)行之后會(huì)輸出什么?
var intervalId, timeoutId;
timeoutId=setTimeout(function() {
console.log(1);
}, 300);
setTimeout(function() {
clearTimeout(timeoutId);
console.log(2);
}, 100);
setTimeout('console.log("5")', 400);
intervalId=setInterval(function() {
console.log(4);
clearInterval(intervalId);
}, 200);
// 分別輸出: 2、4、5
setInterval 和 setTimeout的區(qū)別?
// 執(zhí)行下面的代碼塊會(huì)輸出什么?
setTimeout(function() {
console.log('timeout');
}, 1000);
setInterval(function() {
console.log('interval')
}, 1000);
// 輸出一次 timeout,每隔1S輸出一次 interval
/*--------------------------------*/
// 通過(guò)setTimeout模擬setInterval 和 setInterval有啥區(qū)別么?
varcallback=function() {
if(times++ > max) {
clearTimeout(timeoutId);
clearInterval(intervalId);
}
console.log('start', Date.now() - start);
for(var i=0; i < 990000000; i++) {}
console.log('end', Date.now() - start);
},
delay=100,
times=0,
max=5,
start=Date.now(),
intervalId, timeoutId;
functionimitateInterval(fn, delay) {
timeoutId=setTimeout(function() {
fn();
if(times <=max) {
imitateInterval(fn ,delay);
}
}, delay);
}
imitateInterval(callback, delay);
intervalId=setInterval(callback, delay);
如果是setTimeout和setInterval的話(huà),它倆僅僅在執(zhí)行次數(shù)上有區(qū)別,setTimeout一次、setIntervaln次。
而通過(guò)setTimeout模擬的setInterval與setInterval的區(qū)別則在于:setTimeout只有在回調(diào)完成之后才會(huì)去調(diào)用下一次定時(shí)器,而setInterval則不管回調(diào)函數(shù)的執(zhí)行情況,當(dāng)?shù)竭_(dá)規(guī)定時(shí)間就會(huì)在事件隊(duì)列中插入一個(gè)執(zhí)行回調(diào)的事件,所以在選擇定時(shí)器的方式時(shí)需要考慮setInterval的這種特性是否會(huì)對(duì)你的業(yè)務(wù)代碼有什么影響?
setTimeout(func, 0) 和 setImmediate(func)誰(shuí)更快?
console.time('immediate');
console.time('timeout');
setImmediate(()=> {
console.timeEnd('immediate');
});
setTimeout(()=> {
console.timeEnd('timeout');
}, 0);
在Node.JS v6.7.0中測(cè)試發(fā)現(xiàn)setTimeout更早執(zhí)行
下面代碼運(yùn)行后的結(jié)果是什么?
// 題目一
var t=true;
setTimeout(function(){
t=false;
}, 1000);
while(t){}
alert('end');
// 題目二
for(var i=0; i < 5; i++) {
setTimeout(function() {
console.log(i);
}, 0);
}
// 題目三
var obj={
msg: 'obj',
shout: function() {
alert(this.msg);
},
waitAndShout: function() {
setTimeout(function() {
this.shout();
}, 0);
}
};
obj.waitAndShout();
在講解上面面試題的答案之前,我們先要理解一下定時(shí)器的工作原理,以方便理解上面的題目
這里將用引用How JavaScript Timers Work中的例子來(lái)解釋定時(shí)器的工作原理,該圖為一個(gè)簡(jiǎn)單版的原理圖。
在這圖中,左側(cè)數(shù)字代表時(shí)間,單位毫秒;
左側(cè)文字代表某一個(gè)操作完成后,瀏覽器去詢(xún)問(wèn)當(dāng)前隊(duì)列中存在哪些正在等待執(zhí)行的操作;
藍(lán)色方塊表示正在執(zhí)行的代碼塊;
右側(cè)文字代表在代碼運(yùn)行過(guò)程中,出現(xiàn)哪些異步事件。
大致流程如下:
1.程序開(kāi)始時(shí),有一個(gè)JS代碼塊開(kāi)始執(zhí)行,執(zhí)行時(shí)長(zhǎng)約為18ms,在執(zhí)行過(guò)程中有3個(gè)異步事件觸發(fā),其中包括一個(gè)setTimeout、鼠標(biāo)點(diǎn)擊事件、setInterval
2.第一個(gè)setTimeout先運(yùn)行,延遲時(shí)間為10ms,稍后鼠標(biāo)事件出現(xiàn),瀏覽器在事件隊(duì)列中插入點(diǎn)擊的回調(diào)函數(shù),稍后setInterval運(yùn)行,10ms到達(dá)之后,setTimeout向事件隊(duì)列中插入setTimeout的回調(diào)
當(dāng)?shù)谝粋€(gè)代碼塊執(zhí)行完成后,瀏覽器查看隊(duì)列中有哪些事件在等待,他取出排在隊(duì)列最前面的代碼來(lái)執(zhí)行
3.在瀏覽器處理鼠標(biāo)點(diǎn)擊回調(diào)時(shí),setInterval再次檢查到到達(dá)延遲時(shí)間,他將再次向事件隊(duì)列中插入一個(gè)interval的回調(diào),以后每隔指定的延遲時(shí)間之后都會(huì)向隊(duì)列中插入一個(gè)回調(diào)
4.后面瀏覽器將在執(zhí)行完當(dāng)前隊(duì)頭的代碼之后,將再次取出目前隊(duì)頭的事件來(lái)執(zhí)行
在這也只是對(duì)定時(shí)器的工作原理做了簡(jiǎn)單的敘述,其實(shí)實(shí)際的實(shí)現(xiàn)處理過(guò)程會(huì)更加復(fù)雜。
在我們理解了定時(shí)器的運(yùn)行原理之后,接下來(lái)我們就基于運(yùn)行原理的基礎(chǔ)上,來(lái)看看上面的經(jīng)典面試題的答案
第一題
alert永遠(yuǎn)都不會(huì)執(zhí)行,因?yàn)镴S是單線(xiàn)程的,且定時(shí)器的回調(diào)將在等待當(dāng)前正在執(zhí)行的任務(wù)完成后才執(zhí)行,而while(t) {}直接就進(jìn)入了死循環(huán)一直占用線(xiàn)程,不給回調(diào)函數(shù)執(zhí)行機(jī)會(huì)
第二題
代碼會(huì)輸出 5 5 5 5 5,理由同上,當(dāng)i=0時(shí),生成一個(gè)定時(shí)器,將回調(diào)插入到事件隊(duì)列中,等待當(dāng)前隊(duì)列中無(wú)任務(wù)執(zhí)行時(shí)立即執(zhí)行,而此時(shí)for循環(huán)正在執(zhí)行,所以回調(diào)被擱置。當(dāng)for循環(huán)執(zhí)行完成后,隊(duì)列中存在著5個(gè)回調(diào)函數(shù),他們的都將執(zhí)行console.log(i)的操作,因?yàn)楫?dāng)前JS代碼上中并沒(méi)有使用塊級(jí)作用域,所以i的值在for循環(huán)結(jié)束后一直為5,所以代碼將輸出5個(gè)5
第三題
這個(gè)問(wèn)題涉及到this的指向問(wèn)題,由setTimeout()調(diào)用的代碼運(yùn)行在與所在函數(shù)完全分離的執(zhí)行環(huán)境上. 這會(huì)導(dǎo)致這些代碼中包含的this關(guān)鍵字會(huì)指向window (或全局)對(duì)象,window對(duì)象中并不存在shout方法,所以就會(huì)報(bào)錯(cuò),修改方案如下:
var obj={
msg: 'obj',
shout: function() {
alert(this.msg);
},
waitAndShout: function() {
var self=this; // 這里將this賦給一個(gè)變量
setTimeout(function() {
self.shout();
}, 0);
}
};
obj.waitAndShout();
1.setTimeout有最小時(shí)間間隔限制,HTML5標(biāo)準(zhǔn)為4ms,小于4ms按照4ms處理,但是每個(gè)瀏覽器實(shí)現(xiàn)的最小間隔都不同
2.因?yàn)镴S引擎只有一個(gè)線(xiàn)程,所以它將會(huì)強(qiáng)制異步事件排隊(duì)執(zhí)行
3.如果setInterval的回調(diào)執(zhí)行時(shí)間長(zhǎng)于指定的延遲,setInterval將無(wú)間隔的一個(gè)接一個(gè)執(zhí)行
4.this的指向問(wèn)題可以通過(guò)bind函數(shù)、定義變量、箭頭函數(shù)的方式來(lái)解決
*請(qǐng)認(rèn)真填寫(xiě)需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。