時(shí)間:2023-07-21 20:21:01 | 來(lái)源:網(wǎng)站運(yùn)營(yíng)
時(shí)間:2023-07-21 20:21:01 來(lái)源:網(wǎng)站運(yùn)營(yíng)
時(shí)間之美 —— SpriteJS 的原創(chuàng)時(shí)間軸設(shè)計(jì):let startTime = Date.now(), T = 2000requestAnimationFrame(function update(){ let p = (Date.now() - startTime) / T ball.style.transform = `rotate(${360 * p}deg)` requestAnimationFrame(update)})
上面的代碼我們實(shí)現(xiàn)一個(gè)小球圍繞圓心做勻速圓周運(yùn)動(dòng)運(yùn)動(dòng)的動(dòng)畫,這是一個(gè)基于時(shí)間的動(dòng)畫,我們根據(jù)當(dāng)前時(shí)間改變?cè)氐膖ransform樣式,通過(guò)requestAnimationFram來(lái)更新,這樣就實(shí)現(xiàn)了。T=2000
改成T=1000
:let startTime = Date.now(), T = 1000requestAnimationFrame(function update(){ let p = (Date.now() - startTime) / T ball.style.transform = `rotate(${360 * p}deg)` requestAnimationFrame(update)})
小球運(yùn)動(dòng)方向是順時(shí)針旋轉(zhuǎn),如果我們要讓小球逆時(shí)針旋轉(zhuǎn),我們可以改變r(jià)otate的符號(hào):let startTime = Date.now(), T = 1000requestAnimationFrame(function update(){ let p = (Date.now() - startTime) / T ball.style.transform = `rotate(${-360 * p}deg)` requestAnimationFrame(update)})
如果頁(yè)面上還有其他動(dòng)畫對(duì)象,我們同樣可以添加進(jìn)來(lái),比如我們?cè)谛∏蚺赃吿砑右粋€(gè)顏色從紅色漸變到藍(lán)色的方塊:const startTime = Date.now()requestAnimationFrame(function update(){ let p = (Date.now() - startTime) / 2000 ball.style.transform = `rotate(${-360 * p}deg)` requestAnimationFrame(update)})requestAnimationFrame(function update(){ let p = (Date.now() - startTime) / 5000 p = Math.min(p, 1.0) let red = Math.round(255 * (1 - p)), blue = Math.round(255 * p) block.style.backgroundColor = `rgb(${red},0,${blue})` if(p < 1.0) { requestAnimationFrame(update) }})
現(xiàn)在我們要改變動(dòng)畫的速度或者方向就稍微麻煩一點(diǎn)點(diǎn)了,因?yàn)槲覀冇袃蓚€(gè)獨(dú)立的動(dòng)畫要修改參數(shù)。但是如果有類似于將所有動(dòng)畫速度提升到原來(lái)的2倍這樣的需求時(shí),我們有一個(gè)最簡(jiǎn)單的方法,那就是修改時(shí)間流動(dòng)的速度。const timeline = new Timeline()requestAnimationFrame(function update(){ let p = timeline.currentTime / 2000 ball.style.transform = `rotate(${-360 * p}deg)` requestAnimationFrame(update)})requestAnimationFrame(function update(){ let p = timeline.currentTime / 5000 p = Math.min(p, 1.0) let red = Math.round(255 * (1 - p)), blue = Math.round(255 * p) block.style.backgroundColor = `rgb(${red},0,${blue})` if(p < 1.0) { requestAnimationFrame(update) }})
改寫后的代碼跟之前的代碼相比,幾乎沒(méi)有什么不同,唯一的不同之處是原先的Data.now() - startTime
被更加簡(jiǎn)單的timeline.currentTime
所取代了。const timeline = new Timeline({playbackRate: 0.5, originTime: 2000})console.log(Math.round(timeline.currentTime / 100) / 10)setInterval(() => { console.log(Math.round(timeline.currentTime / 100) / 10)}, 1000)
我們會(huì)看到實(shí)際上每隔1秒鐘,timeline的currentTime變化0.5秒,而且時(shí)間從-2秒開(kāi)始變化。const timeline = new Timeline({playbackRate: 0.5, originTime: 1500})requestAnimationFrame(function update(){ let p = timeline.currentTime / 2000 ball.style.transform = `rotate(${-360 * p}deg)` requestAnimationFrame(update)})requestAnimationFrame(function update(){ let p = timeline.currentTime / 5000 p = Math.min(p, 1.0) let red = Math.round(255 * (1 - p)), blue = Math.round(255 * p) if(p > 0) { block.style.backgroundColor = `rgb(${red},0,${blue})` } if(p < 1.0) { requestAnimationFrame(update) }})
我們會(huì)看到,經(jīng)過(guò)這樣的修改之后,兩個(gè)元素動(dòng)畫的速度都減半,而且方塊在3秒鐘(真實(shí)世界的3秒,timeline世界的1.5秒)之后才開(kāi)始改變顏色。const timeline = new Timeline({playbackRate: 2.0, originTime: 1500})requestAnimationFrame(function update(){ let p = timeline.currentTime / 2000 ball.style.transform = `rotate(${-360 * p}deg)` requestAnimationFrame(update)})requestAnimationFrame(function update(){ let p = timeline.currentTime / 6000 p = Math.min(p, 1.0) let red = Math.round(255 * (1 - p)), blue = Math.round(255 * p) if(p > 0) { block.style.backgroundColor = `rgb(${red},0,${blue})` } if(p >= 1.0) { timeline.currentTime = 0 } requestAnimationFrame(update)})
我們可以改變playbackRate,動(dòng)畫速度(和方向)會(huì)立即改變,比如下面這個(gè)例子,我們把鼠標(biāo)移入右邊的方塊時(shí),動(dòng)畫的速度和方向都會(huì)立即改變:const timeline = new Timeline({playbackRate: 1.0, originTime: 1500})requestAnimationFrame(function update(){ let p = timeline.currentTime / 2000 ball.style.transform = `rotate(${-360 * p}deg)` requestAnimationFrame(update)})requestAnimationFrame(function update(){ let p = timeline.currentTime / 6000 p = Math.min(p, 1.0) let red = Math.round(255 * (1 - p)), blue = Math.round(255 * p) if(p > 0) { block.style.backgroundColor = `rgb(${red},0,${blue})` } if(p >= 1.0) { timeline.currentTime = 0 } else if(p < 0) { timeline.currentTime = 6000 } requestAnimationFrame(update)})block.addEventListener('mouseenter', (evt) => { timeline.playbackRate = -2.0})block.addEventListener('mouseleave', (evt) => { timeline.playbackRate = 1.0})
const timeline = new Timeline({playbackRate: 2.0})setInterval(() => { globalTime.innerHTML = parseInt(globalTime.innerHTML, 10) + 1}, 1000)timeline.setInterval(() => { timelineTime.innerHTML = parseInt(timelineTime.innerHTML, 10) + 1}, 1000)
這個(gè)例子timeline的setInterval實(shí)際觸發(fā)時(shí)間是500毫秒(1000毫秒/2.0)const t1 = new Timeline({playbackRate: 1.0}), t2 = new Timeline({playbackRate: -1.0})t1.setTimeout(() => { console.log(t1.currentTime)}, 1000)t2.setTimeout(() => { console.log(t2.currentTime)}, -1000)
t1和t2的timer幾乎同時(shí)觸發(fā),t1時(shí)間方向是正向,t2時(shí)間方向是負(fù)向。const t1 = new Timeline({playbackRate: -1.0}), t2 = new Timeline({playbackRate: 1.0})t1.setTimeout(() => { console.log(t1.currentTime)}, 1000)t2.setTimeout(() => { console.log(t2.currentTime)}, -1000)
兩個(gè)timer都立即觸發(fā),因?yàn)樗鼈兊?b>當(dāng)前時(shí)間都在timer的時(shí)間之后。const t1 = new Timeline({playbackRate: -1.0}), t2 = new Timeline({playbackRate: 1.0})t1.setTimeout(() => { console.log(t1.currentTime)}, {delay: 1000, heading: false})t2.setTimeout(() => { console.log(t2.currentTime)}, -1000)
上面的例子t1的timer不會(huì)觸發(fā),t2的timer會(huì)觸發(fā),因?yàn)閠1設(shè)置了heading:false。const t1 = new Timeline({playbackRate: -1.0}), t2 = new Timeline({playbackRate: 1.0})t1.setTimeout(() => { console.log(t1.currentTime)}, {delay: 1000, heading: false})t2.setTimeout(() => { console.log(t2.currentTime) t1.playbackRate = 1.0}, 1000)
const timeline = new Timeline(), forkedTimeline1 = timeline.fork(), forkedTimeline2 = timeline.fork()const startTime = Date.now()const globalTime = document.getElementById('globalTime'), localTime = document.getElementById('localTime'), forkedTime1 = document.getElementById('forkedTime1'), forkedTime2 = document.getElementById('forkedTime2')forkedTimeline1.playbackRate = 2.0forkedTimeline2.playbackRate = -2.0setInterval(() => { globalTime.innerHTML = `${Math.round((Date.now() - startTime) / 1000)}s` localTime.innerHTML = `${Math.round(timeline.currentTime / 1000)}s` forkedTime1.innerHTML = `${Math.round(forkedTimeline1.currentTime / 1000)}s` forkedTime2.innerHTML = `${Math.round(forkedTimeline2.currentTime / 1000)}s`}, 100)
上面的例子里,forkedTimeline1和forkedTimeline2都是從localTimeline分支出來(lái)的,所以我們改變localTime,就能同時(shí)改變forkedTimeline1和forkedTimeline2,比如現(xiàn)在forkedTimeline1的時(shí)間線是正向,forkedTimeline2的時(shí)間線是負(fù)向,我們只要把localTimeline的playbackRate設(shè)置為-1,那么forkedTimeline1時(shí)間線變成負(fù)向,forkedTimeline2的時(shí)間線則變成正向。let timeline = new Timeline()function count(el, timeline, p = Infinity) { timeline.setInterval(() => { el.innerHTML = Math.round(timeline.currentTime / 1000) % p }, 1000)}count(ball0, timeline)count(ball1, timeline.fork({playbackRate: 10}), 10)count(ball2, timeline.fork({playbackRate: 100}), 10)
const [speedupBtn, slowdownBtn, pauseBtn, playBtn] = ['Speed up', 'Slow down', 'Pause', 'Play'].map((type, i) => { const button = new Button(type) button.attr({ anchor: [0.5, 0.5], pos: [1300, 400 + 150 * i], size: [170, 50], font: '36px Arial', lineHeight: 50, textAlign: 'center', color: '#00e15e', border: [3, '#00e15e'], borderRadius: 25, padding: 30, }) bglayer.appendChild(button) return button }) speedupBtn.on('click', (evt) => { fglayer.timeline.playbackRate += 0.2 }) slowdownBtn.on('click', (evt) => { fglayer.timeline.playbackRate -= 0.2 }) pauseBtn.on('click', (evt) => { fglayer.timeline.playbackRate = 0 }) playBtn.on('click', (evt) => { fglayer.timeline.playbackRate = 1 })
以上就是關(guān)于sprite-timeline的關(guān)鍵內(nèi)容,其他還有一些有趣的功能,在這里沒(méi)有列出,比如timeline的“熵”(entropy),以及entropy相關(guān)的用法,有興趣的同學(xué)可以關(guān)注GitHub repo自行研究。關(guān)鍵詞:設(shè)計(jì)
客戶&案例
營(yíng)銷資訊
關(guān)于我們
客戶&案例
營(yíng)銷資訊
關(guān)于我們
微信公眾號(hào)
版權(quán)所有? 億企邦 1997-2025 保留一切法律許可權(quán)利。