2022-06-16 分類: 解決方案
今天聊的內容是淘寶虛擬互動實驗室的@渚薰大神 在2017年06月在北京GMTC大會上分享的一個主題。未能親臨聽到相關的精彩分享,但還算是有幸的,在內部聽到@渚薰大神 的分享。個人對Web動畫這方面的課程非常的感興趣,而且現在和團隊一直在致力于手淘互動動效相關的研究。經歷了從Gif、視頻到CSS Animation的零至一的過程,并且致力于JavaScript驅動的動效開發,以及現在致力于研究的數據化驅動的動效。這樣的一個過程是幸福的,而且也是具有挑戰力的。我想很多喜歡動畫的同學也對這樣的一個課程會感興趣,所以接下來,我們根據@渚薰大神分享的PPT的思路來聊聊漸進式動畫解決方案。
PWA
最早聽到PWA(Progressive Web Apps)這樣的一個概念是2016年在上海Qcon的分享會上聽到@黃弦 大大的分享,但我們今天要聊的并不是Progressive Web APPs,而是其變身Progressive Web Animation。我們把其稱為漸進式動畫。那問題來了,什么才是漸進式動畫呢?這是值得每位愛好動畫的同學去思考的?為了更好的闡述自己對漸進式動畫的理解,將分幾個方向來介紹:
重新認識動畫
如何操作動畫
如何管理動畫
如何制作動畫
重新思考動畫
接下來一一聊聊。
要重新認識動畫,那么其中有兩個非常重要的概念:動效和插值。
動效是源于電影動效。動效是錄音學范疇,簡言之,指各種動作的聲音效果,又被稱為擬聲。比如武打片里,骨折的聲音是芹菜制造的,下雨的聲音是由洗臉的聲音制造的。
看上并不是我們所要說的動效,這并不要緊。如果需要和我們的實際工作中緊密聯合在一起,我們的Web也可以有音效,特別是早期的Flash,各種的配合音效,得到與眾不同的效果。隨著CSS和HTML以及JavaScript相關技術不斷的革新,同時各種特性能得到眾多現代瀏覽器的支持。現在的Web展示形式也不斷的變化,不管是Web頁面或者說APP應用,都會或多或少的添加一些動效效果。
俗話說得好,顏值不夠,動效來湊,Web動效已經不僅僅是Web設計的潤滑劑了,它的功能更多的體現在交互邏輯、視覺渲染和創新實踐上,上能引人注目,下能潛移默化。對于Web開發人員而言,更喜歡把這些動效稱之為Web動畫。為了接地氣,后面也將稱之為動畫。
迪士尼動畫大師乃特維克的畢生經驗對Web動畫濃縮成一句話:
動畫的一切皆在于時間點和空間幅度!
事實上,動效設計和做動畫是一脈相通的,我們不要做寫實主義的動畫,而是要通過時間點和空間幅度的設置為用戶建立運動的可信度。這樣描述感覺有點繞。其實我們可以這樣來描述動畫的概念:
動畫是指由許多幀靜止的畫面,以一定的速度(比如每秒16張)連續播放時,肉眼因視覺殘象產生錯覺,而誤以為畫面活動的作品。為了得到活動的畫面,第個畫面之間都會有細微的改變。
其實我更喜歡說動畫就是以時間置換空間。比如下圖:
圖形A狀態(一個正方形)經過時間的變換到了圖形B的狀態(一個圓形)。從正方形變成圓形這樣的一個過程就是一個動畫效果(動效)。當然為了制作這樣的一個動畫,會添加控制動畫的一些手段,比如控制持續時間、延遲時間、緩動函數、動畫次數和方向之類的等。當然根據不同的制作動畫的方式,這些控制動畫的參數或者說手段吧,其方法不一樣。這里暫且不深入的介紹。
剛才也說過了,這樣的一個過程就是一個動畫效果,專業一點稱之為Motion Effect。而這個Motion Effect又受眾多因素的影響。同樣拿上面的示例來說,正方形是一下子變成圓形呢還是慢慢的變形圓形呢?又是經過多少時間才變成圓形呢?這一切的一切都會影響到。而其中有一個較好的方案就是在運動的過程中將插值引進來。
這里所說的插值其實是指線性插值。線性插值是數學、計算機圖形學等領域廣泛的一種簡單插值方法。在平常實際運用當中,把插值稱之為lerp,簡單而言:
lerp是兩點之間的線性插值的別稱。
同樣的回到面的示例,正方形狀態A是一個點,圓形狀態B是一個點。如果我們把狀態A稱為0點,把狀態B稱為1點。那么在這個過程中我們可以有很多個值,比如0.1、0.2....9之類,比如下圖所示:
從0至1這樣的一個過程就是一個插值過程。用到圖形變化中來,比如正方形是四個點連起的圖形,那么變成圓形,這個點數越多這個圓就越圓,比如16、32、64、128等等,也可以說點數越多,越趨向于圓。而這個程,我們使用插值原理來計算,效果會更佳。比如下面兩個圖:
一個高級動畫或者動畫藝術家都手繪的關鍵幀定義的一個動畫。不管你是怎么一個高級的動畫設計師,手繪總是有所限制的,如果我們換成插值來繪制:
插值能增加很多中間幀,讓動效變得更為絲滑。
上面演示的是幀之間的插值,事實上我們除了這個之外,還有顏色的插值,圖形插值等等。這里想要表達的觀點是:插值能讓動效變得更為絲滑。有關于插值方面的相關介紹,可以閱讀:
理解動畫中的線性插值
如何操作動畫
操作一個動畫,其實具有兩個過程,其一制作動畫的場景,其二拼接動畫場景。把它們結合起來就是操作一個動畫。那么操作一個動畫,就目前的技術常見的有:
CSS Animation
SVG Animation
JavaScript-Driven Animation
我想大家最早接觸動畫的控制方式應該類似于jQuery的.animate():
$( "#clickme" ).click(function() {
$( "#book" ).animate({
opacity: 0.25,
left: "+=50",
height: "toggle"
}, 5000, function() {
// Animation complete.
});
});
對于這種制作動畫的方式不做過多的評介。但隨著CSS技術的發展,使用純CSS就可以很好的實現Animation。在CSS中主要是使用@keyframes和animation-*屬性來控制動畫。CSS Animation雖然實現一個動效較為容易,成本也較低,但對于一些復雜的動畫場景,他就變得非常的雞肋。除此之外,這兩年SVG Animation也越來越多在實際場景中使用。
不過,這里需要特別提出的是JavaScript-Driven Animation,也就是JavaScript驅動動畫。最簡單的就是W3C規范提供的Web Animation API簡稱為WAAPI。其原理非常類似于CSS Animation,具有@keyframes的概念,也具有類似于animation-*屬性樣的方法,用于控制動畫。同時還提供了對應的Timeline的概念,而Timeline又是動畫中一個至關重要的一個概念,稍后或多或少會介紹一些。
雖然有了WAAPI,可以使用原生的JavaScript制作動畫,但還是有一些功能性的限制,而且實現方式,制作流程等等,都有待于改善。但對于Web社區而言,這一切都不是問題。因為很多開發者,都會針對于自己的業務,或者說自己的需求,在某一方面做出優秀的成績,并且分享給社區。正因為如此,社區中有很多使用JavaScript來驅動動畫的庫,比如:GreenSock、CreateJS、Anime和Motion等:
不管是哪種制作動畫的JavaScript庫或者說工具都有各自的利弊。只能說選擇最適合自己的,俗話說:
站在巨人的肩膀上,看得比別人更遠些。(If I have been able to see further, it was only because I stood on the shoulders of giants.)
除了上述制作動畫之外,我們還可以采用Canvas和WebGL。特別是WebGL,在當今算是一個熱門的話題,國內外很多團隊都在研究這方面的技術,其中最具代表性的作品就是ThreeJS。
制作動畫另一個不可避免的問題,那就是動畫的性能問題。這是一個很深的、很復雜的話題。不過我們可以借助一些其他的工具幫助我們在底層做一些變化,比如采用GPU來渲染:
GPU.JS:使用JavaScript給GPU加速
PixiJS:一個HTML5引擎,也是最靈活的2D WebGL渲染器
除了借助工具之外,我們也可以在自己的代碼層面做一些優化,比如使用requestAnimationFrame這個API:
const raf = requestAnimationFrame;
const running = [];
const idle = [];
export const add = tick => running.push(tick);
export const remove = id => (running[id] = idle[id] = undefined);
export const run = () => raf(function tok() {
raf(tok);
running.forEach(t => t());
});
export const pause = id => (idle[id] = running[id]) && (running[id] = undefined);
export const resume = id => (running[id] = idle[id]) && (idle[id] = undefined);
有關于這方面的介紹大家可以閱讀下面幾篇文章:
requestAnimationFrame for Smart Animating
requestAnimationFrame API: now with sub-millisecond precision
Using requestAnimationFrame
Animating with javascript: from setInterval to requestAnimationFrame
CSS3動畫那么強,requestAnimationFrame還有毛線用?
requestAnimationFrame
使用requestAnimationFrame更好的實現javascript動畫
requestAnimationFrame 性能更好
以前在站上也整理了一些優化動畫性能的相關文章,對這方面感興趣的同學可以閱讀下面的文章:
使用瀏覽器開發者工具檢測CSS動畫性能
CSS Animation性能優化
高性能的動畫
使用CSS3實現60FPS動畫
使用 FLIP 來提高 Web 動畫的性能
CSS動畫之硬件加速
制作出來動畫,我們可以將整體的動畫細分出來,那么怎么管理動畫變得就很重要了。我常常喜歡把動畫比喻成一場舞臺劇,整個劇會有演員,演員什么時候出場之類的。而控制演員出場順序和時間之類的由導演來負責。回到我們的動畫中來,我們可以把整個動畫當作一個舞臺劇(一個故事),故事中有很多個片段(也就是我們的動畫分場景),而串起整個動畫是由時間軸來控制,常常稱之為Timeline。
比如:
正如上圖所示,這里有三輛小汽車向右行駛的動效,那么藍、黃、紅怎么出現,就由時間軸來控制了。而整個過程,它其實也是一個流式的過程。有接觸過Flash的同學應該知道。在Flash中有兩種動畫方式:
流式動畫
所謂流式動畫,就是像電影那樣按既定順序一直播放,不會停,也不會發生改變的動畫。你在電視上看到的所有動畫片都可以說是流式動畫。流式動畫最顯著的特點就是你無法對流式動畫施加影響,比如你無法期待單擊流式動畫中的某個器物(動畫元素)而指望因此而發生什么事情。總之,流式動畫中所有的一切都是注定的,有一種宿命的感覺。盡管流式動畫的能力有限,但不可否認,流式動畫的應用還是非常廣泛的。
說到這里,大家可能會想到,我們CSS Animation。眾所周知,一旦我們定制好了一個CSS Animation,我們是無法通過一些事情讓動畫中的某些動畫元素做其他的事情。這也是令我們頭痛的地方之一。比如我們做一個互動的動畫,希望動畫播放到一定的位置,彈一個彈框出來,告訴用戶你可以領起紅包了。
除了流式動畫,還有一種交互式動畫。所謂交互式動畫,簡單地說就是動畫隨時準備因你的命令或某些事件的出現而發生變化。例如,當你用鼠標點擊動畫中一只小狗的頭時,它會高興地沖你搖尾巴。在這里,鼠標的單擊就是一個命令(或者說是一個事件),而小狗搖尾巴就是對這個命令(或說事件)的響應,整個過程就可以被看作是一次交互。
到目前為止,僅使用CSS Animation,或者后面將提到的一些制作動畫的IDE或軟件,他們做出來的動畫都是流式動畫,只能通過時間軸來控制動畫,整個動畫中沒有任何可交互性而言,這對于大多數業務場景是無法達到需求方的要求。但對于JavaScript驅動的動畫而言,我們的交互行為就要豐富的多,比如SVG Animation,Canvas Animation等。
感覺有點跑題了,這一節我們要說的是管理動畫,其實除了管理動畫中的交互行為之外,更為重要的是管理動畫的播放。前面也提到過了,不管是CSS Animation動畫,還是JavaScript驅動的動畫,都是通過Timeline來管理。只不過JavaScript更具優勢。來看兩個小場景。
先來看CSS Animation中的Timeline,如下圖所示:
上圖演示的是一個紅包火山的動畫場景(喜歡手淘的同學,應該在去年的雙十一看到過這樣的動畫),在這個動畫中我們包括了火山升起(valcaoRising)、火焰柱噴發(expulsion)、巖漿流動(flow)和紅包噴發(blowout)。在這個動畫中,我們要人工的去計算動畫的延遲時間(animation-delay)和持續時間(animation-duration)。比如火山升起,我們花費了1s,火焰柱噴發等火山升起才開始,這樣一來,其延遲時間為1s,并且持續了.4s,在此同時巖漿流動的效果也同時發生,也就是說巖漿流動的延遲時間也是1s,而其持續了2s,其實動畫進行到1.4s時,火焰柱噴發的動效是已經停止了。除此之外,還有紅包噴發的一個動畫,而這個動畫是在火焰柱噴發結束的時候開始,這樣其延遲時間是1.4s,并且持續了15s。其實整個動效花了16.4s。
如果這樣做就能滿足業務方的需求,那是開發者的福音,但是要變動某個時間,比如火山升起需要持續2s,那么后續的三個動畫的時間都需要變更。而這個過程是一個痛苦的過程。
但在JavaScript驅動的動畫中,我們依舊是通過Timeline來管理動畫,但會變得輕松和靈活的多,比如下圖:
在JavaScript中,我們可以通過技術手段,將相關功能封裝成函數,然后在動畫流中調用:
add(me) => (
playAt: () => number
) => assign(me, {playAt});
tick(elapsed) => queue.forEach(me => {
if (me.playAt() >= elapsed && !me.started)
me.start();
});
同樣拿上圖來說,如果我給火山升起通過playAt()來得到起始時間,并且函數能拿到其停止時間,并且在其停止的這個時候通知其他動畫什么時候開始播放。這樣我們控制動畫會變得輕松的多。哪怕是我們需要改變其中某一個或某兩個的時間,也可以很好的自動獲取。
() => me1.finished;
let fetched;
fetch(url).then(() => fetched = true);
() => fetched;
() => store.getState() === ‘BTN_CLICKED’;
() => me2.started && (me2.startAt + 500);
簡單點講,我們把動畫的控制、決定和管理都交互兩個函數,比如playAt()和stopAt。比如下圖:
這樣是不是感覺爽得多了。
其實前面我們簡單的提到了如何制作動畫,比如通過CSS Animation、SVG Animation或者說JavaScript。但在這一節,我們繼續來聊這個話題。在具體聊這個話題之前,咱們先來看一下開發者和設計者之間的合作關系。
早期的Gif動畫、視頻動畫或者說Flash動畫,這些可以說都不需要開發人員去做什么(這些都是流式動畫,無交互可言)。但隨著市場的變化或者說技術革新后,開發人員想嘗試著新的技術來實現動畫,并且在提供給業務方,這樣做多NB,跟老板說,這樣能節約多少成本。沒想到,這個時候自己挖了一個巨坑讓自己和自己的小伙伴跳進坑中。
別的不說,咱先上一張圖:
可以說這是一個痛苦的過程,視覺設計師將想要的動效制作成視頻文件或者Gif文件以及可切圖的PSD文件給開發人員,然后開發人員將Gif動效或者說視頻演示的動畫轉成Web動畫。大家可能會問,這不是蛋疼?為什么需要制作視頻或Gif文件呢?提供一個PSD文件不就行了?其實視覺設計師也是這么認為的。但話說回來,有多少開發人員能不看效果,通過視覺設計師或者說業務方的描述就能理解所需的動效呢?不知道你行不行,反正我經歷之后告訴我,我是不行。
這樣的一個過程,其實也增加了設計師和開發者的溝通成本,也增加了設計師的工作量。特別是當需求變更之后,設計師欲哭無淚。這個時候老板會說,成本、成本、效率、效率。設計師會說麻煩、麻煩。需求方會說,就這樣吧,其實離我需要的還是有差距的。
隨著時間變化,不管是自己的Boss還是需求方,都希望有所改變:動效能不能變得更絲滑一些、效果還原度能不能更接近一些、能不能更有一些創意和創新,能不能玩一些更有意思的...
開發人員心中千萬個草昵瑪就出來了。但活還是要繼續做的,只是換個方式做而以。這也是我和我們團隊小伙伴近一年多來一直在研究的一個課程:可量化和數據驅動。
這個流程讓我們有了更多的變化。視覺設計師專業的做他的設計,開發人員專業的做他的業務開發。為什么這樣說呢?因為動效的轉換我們通過工具或者軟件來實現,然使用JavaScript的將業務插入到轉化后的動效中。
簡單講,我們的開發過程變成了這樣:
其實這樣的過程,并不是我們有的,最早的時候有些團隊使用Animation CC設計動畫,然后直接轉換出Web動畫,它依賴于CreateJS這個庫。另外也有團隊使用After Effects CC制作動畫,然后借助bodymovin將動畫轉出來。其中最具代表性的就是Airbnb的Lottie:
有關于這方面的DEMO,可以點擊這里查閱。
這是別人家的產品,也是巨人的肩膀。其實在Lottie和Bodymovin還沒有開源出來的時候,我們團隊也有一個類似的產品,AFT(Animation Flow Tools)。AFT沒有開源,我不能聊得太多,簡單的說,AFT具有自己的渲染引擎、也可以借用別人的渲染引擎,比如Canvas、Weex之類。但其主要功能和特點是用來管理動畫,擴展動畫。而且AFT也具有類似Lottie的特性,只不過我們的Player層是自己寫的。下面的示例就是使用AFT通過AE轉出來的一個動效,并且在實際項目中運用的:
我們把這樣制作動畫稱之為可量化和數據驅動。主要原理其實在上面也提到過了。這里簡單的復述一下:
通過類似AE這樣的制作動畫的軟件,將動畫導出成一份JSON數據,這份JSON數據將描述動畫。同時使用Player層結合DSL,將JSON數據和業務邏輯整合,完成帶有可交互的動畫。
雖然我們初步完成了這些樣的一個開發模式,但路還很長,我們也在不斷努力。希望有一天能讓她面世,與眾多動畫愛好者共享。
經過這一系列的變化,并且隨著技術越來越先進。我們有必要重新思考動畫。除了思考其制作過程和動畫效果之外,我們更多的時候去思考其中的模式和工程化相關的東西。
在我們的意識中,動畫就是設計師與開發者之間的故事。但有沒有想過,我們可以換一種模式:
上圖我不想用再多的語言來描述,因為這個過程我和我們的團隊還在探討,等哪一天有了答案和大寫一起分享。在這里我們提出一個動畫工程師的職能,那么真正的動畫工程師應該支承擔一些什么呢?又需要去思考些什么呢?我們一起來思考吧,我想有一天會有答案的。
經過一段從事動畫開發的體驗和感受。我和我們的團隊一直在探索一種好的模式,希望這種模式能幫助我們降低開發成本,提高開發效率,滿足更多需求。同時讓自己參與到創意當中,或者在這些方面有一些創新。
本文名稱:漸進式動畫解決方案
網頁地址:http://vcdvsql.cn/news32/167982.html
網站建設、網絡推廣公司-創新互聯,是專注品牌與效果的網站制作,網絡營銷seo公司;服務項目有解決方案等
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯
猜你還喜歡下面的內容