整合營(yíng)銷(xiāo)服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢(xún)熱線(xiàn):

          程序員的圈套,看了他寫(xiě)的javascript時(shí)鐘,老

          程序員的圈套,看了他寫(xiě)的javascript時(shí)鐘,老板忍痛開(kāi)始招設(shè)計(jì)師!

          了程序員做的html5時(shí)鐘,老板不得已立即招了個(gè)設(shè)計(jì)師,這或許是個(gè)圈套!

          一直以來(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í)資料已上傳到群文件!

          程序員做HTML5/javascript時(shí)鐘源碼

          代碼過(guò)長(zhǎng)需要文檔版源碼來(lái)我的前端群570946165,源碼已經(jīng)上傳了!

          需要更多前端學(xué)習(xí)資料/視頻/學(xué)習(xí)方法,請(qǐng)關(guān)注后,私信“學(xué)習(xí)”

          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)看看吧!


          什么是定時(shí)器

          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)


          舉幾個(gè)栗子加深思考


          基本用法

           // 下面代碼執(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í)行


          幾道經(jīng)典的定時(shí)器面試題

          下面代碼運(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í)器的工作原理,以方便理解上面的題目


          JS定時(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();

          需要注意的點(diǎn)

          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)解決


          主站蜘蛛池模板: 日韩动漫av在线播放一区| 亚洲美女视频一区二区三区| 亚洲线精品一区二区三区影音先锋 | 国产成人精品久久一区二区三区av | 亚洲丰满熟女一区二区哦| 日本不卡一区二区视频a| 久久国产三级无码一区二区| 在线观看视频一区二区| 欧美日本精品一区二区三区| 五月婷婷一区二区| 97精品一区二区视频在线观看| 久久se精品动漫一区二区三区| AV天堂午夜精品一区| 国产精品男男视频一区二区三区 | 视频一区视频二区在线观看| 精品一区二区三人妻视频| 日韩一区二区视频| 亚洲av无码一区二区三区人妖 | 久久免费区一区二区三波多野| 岛国精品一区免费视频在线观看 | 乱精品一区字幕二区| 免费一区二区三区| 一区二区三区国产精品| 日韩人妻不卡一区二区三区| 老熟妇仑乱视频一区二区| 国产一区在线mmai| 欧美日韩综合一区二区三区| 国产丝袜一区二区三区在线观看| 国产乱码精品一区三上| 亚洲A∨精品一区二区三区| 亚洲国产成人久久一区WWW| 东京热无码一区二区三区av| 久久久久久综合一区中文字幕| 末成年女AV片一区二区| 无码中文字幕一区二区三区| 免费一区二区三区在线视频| 真实国产乱子伦精品一区二区三区 | 国产成人精品亚洲一区| 一区二区免费电影| 一区二区视频在线| 欧洲精品免费一区二区三区|