當(dāng)前位置: 首頁 > 設(shè)計資訊 > 設(shè)計教程 > 正文

如何用Framer一步步實(shí)現(xiàn)加載動畫

2018-07-16 1694 0

為Apple Watch設(shè)計APP的時候,首要的準(zhǔn)則是讓它保持簡單。Uber 為 Apple Watch設(shè)計的APP是簡單的最好的例子,原因在于它只有3個頁面:

     1.給Uber發(fā)送需求

     2.等待回復(fù)

     3.讓你知道司機(jī)的信息和狀態(tài)

說到動畫,這個 APP每個界面都有不同的加載動畫,這些動畫原型都非常有趣,下面將用 framer實(shí)現(xiàn)這些動畫。

你自己可以跟著我一步步用 framer實(shí)現(xiàn)這個原型,下圖是將要實(shí)現(xiàn)的效果:

43505768cd360000018c1b1b372c.jpg


 

要開始,先下載 Sketch文件(在附件中),在開始前我已經(jīng)用 Sketch自帶的 Apple Watch GUI 在不同畫板之間創(chuàng)建了我們需要的界面,當(dāng)我們把 Sketch文件導(dǎo)入 framer的時候,只有被編組的界面元素才會被 framer識別到,這里要特別注意圖層的組織。

86105768cd510000012e7e11bb30.jpg

在這個例子中,作為第一個屏幕,需要把加載的圓形和 “Request”按鈕分別編組,因?yàn)橹挥羞@兩個元素需要添加交互和動畫,現(xiàn)在,我們的Sketch文件已經(jīng)準(zhǔn)備好了,讓我們導(dǎo)入到framer。


 

我們要做的第一件事是清除代碼編輯器,并將您的設(shè)備切換為蘋果手表。工具欄的右上角去Device ?- ??Apple Watch 42mm?-? 選擇其中一個選項(xiàng)。

8c465768cd700000012e7ebacefe.jpg

保持Sketch處于打開狀態(tài),在 framer中點(diǎn)擊工具欄上的導(dǎo)入按鈕或者用快捷鍵 Command+I喚出導(dǎo)入對話框,確認(rèn)對話框中的 Sketch列表后面的 import按鈕處于激活狀態(tài),點(diǎn)擊導(dǎo)入按鈕導(dǎo)入。

ab7b5768cd8b0000012e7eff7d10.jpg

framer會自動為導(dǎo)入的原型添加注釋和代碼行,我們可以重命名導(dǎo)入文件的名稱使它變簡短,例如 這里重命名為Uber。


 

# This imports all the layers for "uber-watch" into 

uber= framer.importer.load "imported/uber-watch"


 

我們應(yīng)該在右側(cè)的預(yù)覽窗口中看到request界面。我們也可以在中間的檢查面板中查看導(dǎo)入的其他的兩個界面(以淡一點(diǎn)的顏色顯示),因?yàn)樗鼈兪遣豢梢姷摹?/p>

8ecd5768cdb50000018c1bfe13e0.jpg

要創(chuàng)建加載脈動,我們將創(chuàng)建兩個動畫對象。第一個動畫用到 loadingCircle圖層scale 屬性增大10%。如果要訪問我們導(dǎo)入的任何圖層對象,我們只需輸入導(dǎo)入時的文件變量,后面加點(diǎn),然后加圖層組名。按照這種方式,我們將使用uber.loadingcircle指定動畫的層。定義過度時間為1.5秒的脈沖動畫。


 

pulseUp = new Animation

    layer: uber.loadingCircle

    properties:

        scale: 1.1

    time: 1.5


 

第二個動畫是把放大的 loadingCircle圖層,恢復(fù)到原來的狀態(tài),同樣是 1.5秒。


 

pulseDown = new Animation

    layer: uber.loadingCircle

    properties:

        scale: 1.0

    time: 1.5


 

下面將這兩種動畫串聯(lián)起來使得第一種狀態(tài)結(jié)束時自動開始下一種狀態(tài)。

為了串聯(lián)動畫,我們會監(jiān)聽 animationend事件,這個事件的意思當(dāng)一種狀態(tài)結(jié)束時會被調(diào)用。要監(jiān)聽事件,我們將制定動畫對象上面的 “on”關(guān)鍵字來監(jiān)聽這個事件。

當(dāng)pulseUp動畫結(jié)束時,我們希望 pulseDown動畫開始,用動畫對象的 start()函數(shù),因?yàn)檫@是一個函數(shù),所以要在后面加括號。


 

pulseUp.on Events.AnimationEnd, ->

    pulseDown.start()


 

反過來,當(dāng) pulseDown動畫結(jié)束時,我們希望 pulseUp開始。

pulseDown.on Events.AnimationEnd, ->

    pulseUp.start()    


 

需要做的只有開始動畫了。

pulseUp.start()  


 

我們現(xiàn)在應(yīng)該可以看到脈沖動畫了。

d9245768ce2f0000018c1b1341f2.jpg


 

為了切換到下一個界面,要給 requestButton圖層創(chuàng)建一個點(diǎn)擊事件。

requestButton.on Events.Click, ->


 

當(dāng)導(dǎo)入Sketch文件,僅僅第一個畫板界面能看到,為了顯示出 Requesting界面,需要設(shè)置它的 visible屬性為 true,另外為了隱藏 Request界面,需要設(shè)置它的 visible屬性為 false。


 

uber.requestButton.on Events.Click, ->

    uber.request.visible = false

    uber.requesting.visible = true


 

如果仔細(xì)觀察原型,你會發(fā)現(xiàn)過度不平滑,因?yàn)閮H僅是界面瞬間的隱藏和顯示。我們可以做的更好,在 requesting完全顯示之前, 通過設(shè)置 Request界面的透明度的過度動畫為 0.3,然后設(shè)置 requesting的透明度過度到 1。與其創(chuàng)建另一個動畫對象,并告訴它開始,倒不如我們可以直接在事件里面通過圖層名稱.animate啟動的圖層的動畫,然后指定過度動畫的屬性。


 

uber.requestButton.on Events.Click, ->

    uber.requesting.opacity = .3

    uber.request.visible = false

    uber.requesting.visible = true

    uber.requesting.animate    

        properties:

            opacity: 1


 

現(xiàn)在原型的效果如下:

715a5768ce650000012e7e38dd2c.jpg

在真實(shí)的Apple Watch中,點(diǎn)擊 request按鈕后就是展示加載界面,最后才是顯示下一個界面。

在Requesting界面中一致播放脈動加載條的動畫直到有司機(jī)確認(rèn),但是這里有一個回到 request界面的取消按鈕。這里我們不處理取消按鈕的事件,但是你可以自己練習(xí)著完成它。

為了創(chuàng)建這個脈動加載條,先設(shè)置加載條的開始位置,這個加載條就是在 Sketch文件中命名為 requestingLoad的圖層組,這里設(shè)置開始位置通過 scaleX屬性為 0.1且它的不透明度為 0。


 

uber.requestingLoad.scaleX = .1

uber.requestingLoad.opacity = 0  


 

為加載條創(chuàng)建動畫對象,我們想要它從初始狀態(tài)過度到原始的狀態(tài),且伴隨不透明度的增加。這里要通過 repeat選項(xiàng),重復(fù)動畫幾次。


 

requestingPulse= new Animation

        layer: uber.requestingLoad

        properties:

            opacity: .8

            scaleX: 1

        repeat: 5   


 

現(xiàn)在回到第一屏的 request按鈕的點(diǎn)擊事件,切換到過度界面


 

uber.requestButton.on Events.Click, ->

    uber.requesting.opacity = .3

    uber.request.visible = false

    uber.requesting.visible = true

    uber.requesting.animate    

        properties:

            opacity: 1

    

    requestingPulse.start()   


 

現(xiàn)在來添加一個延遲直到想我們希望看到的一樣。


 

requestingPulse= new Animation

        layer: uber.requestingLoad

        properties:

            opacity: .8

            scaleX: 1

        delay: .4

        time: .9

        repeat: 5


 

這里Uber的 requesting界面的效果如下:

d5bb5768ceee0000018c1b3caccd.jpg

為了過度到下一個界面,需要設(shè)定脈沖加載動畫的重復(fù)次數(shù)。每一次 requestingpulse動畫結(jié)束的時候觸發(fā)的animationend 事件,是添加邏輯最好的地方。

首先創(chuàng)建一個 requestingCount變量,它的作用是記錄脈沖次數(shù),設(shè)置初始值為0。我們把它放在animationend事件代碼塊外面,而不是在里面,因?yàn)槿绻阉锩鎸⒚看沃刂脼?,結(jié)果是一個無限循環(huán)。


 

requestingCount = 0


 

在AnimationEnd事件中,它被調(diào)用一次增加計數(shù) 1次,這里我們設(shè)置變量等于它本身加 1即可。


 

requestingPulse.on Events.AnimationEnd, ->

    requestingCount = requestingCount + 1


 

一種簡單的寫法是在變量后面帶兩個加號,效果和上面是一樣的。


 

requestingPulse.on Events.AnimationEnd, ->

    requestingCount++


 

在計算次數(shù)等于希望的動畫重復(fù)播放次數(shù),添加切換到下一個界面的邏輯,這里我們設(shè)定希望動畫重復(fù)的次數(shù)為 3。


 

requestingPulse.on Events.AnimationEnd, ->

    requestingCount++

    if requestingCount is 3


 

當(dāng)計算次數(shù)為 3的時候,我們要做和 Request界面切換到 Requesting界面一樣的切換效果來切換到下一個界面。首先設(shè)置下一個界面( enroute)的不透明度為 0.3, requesting圖層的 visible的屬性為 false, enroute界面的 visible的屬性為 true,在讓透明度的過度更平滑一些。


 

requestingPulse.on Events.AnimationEnd, ->

    requestingCount++

    if requestingCount is 3

        uber.enroute.opacity = .3

        uber.requesting.visible = false

        uber.enroute.visible = true

        uber.enroute.animate    

            properties:

                opacity: 1


 

代替計算次數(shù)的做法,你也可以選用在 requesting界面經(jīng)過幾秒之后自動切換到下一個界面(提示:使用 Utils.delay 來做)。記住這是一個原型,所以它不必是完美的,所有選用那種方式更快或更好才是關(guān)鍵。

效果如下:

ea685768cf520000012e7e72879f.jpg

對于Uber的erneute界面,在Sketch文件中命名為 enRouteProgress進(jìn)度條是有旋轉(zhuǎn)動畫的。創(chuàng)建旋轉(zhuǎn)動畫設(shè)置旋轉(zhuǎn)角度為360度, 給旋轉(zhuǎn)動畫添加AnimationEnd事件監(jiān)聽,使旋轉(zhuǎn)結(jié)束繼續(xù)開始下一次旋轉(zhuǎn),重復(fù)次數(shù)可以多一些,也可以設(shè)定旋轉(zhuǎn)一圈所用的時間。


 

enRouteRotate = new Animation

    layer: uber.enRouteProgress

    properties:

        rotation: 360

    repeat: 30

    time: 2


 

可以在前面提到的切換到第三個屏幕的的時候開始播放這個動畫。


 

requestingPulse.on Events.AnimationEnd, ->

    requestingCount++

    if requestingCount is 3

        uber.enroute.opacity = .3

        uber.requesting.visible = false

        uber.enroute.visible = true

        uber.enroute.animate    

            properties:

                opacity: 1

        

        enRouteRotate.start()


 

如果你觀察原型,會發(fā)現(xiàn)不是很平滑。


 

這是因?yàn)閯赢嬊€默認(rèn)是 “ease-in-out”曲線,我們設(shè)置動畫的曲線為 linear。

enRouteRotate= new Animation

    layer: uber.enRouteProgress

    properties:

        rotation: 360

    repeat: 30

    curve: "linear"

    time: 2


 

現(xiàn)在看起來已經(jīng)平滑多了:

eb585768cf850000012e7e6667f0.jpg


 

這個屏幕如果可以滑動應(yīng)該還有更多內(nèi)容。如果你觀察 Sketch中的這個畫板,你會看到這樣的結(jié)構(gòu),可以滾動的內(nèi)容被加上了蒙板。

dfd05768cfd10000012e7edf4fb9.jpg

添加滾動事件是通過在 Sketch中命名為 content的組上創(chuàng)建 ScrollComponent 的wrap 函數(shù)來完成的。


 

scroll= ScrollComponent.wrap uber.content


 

這里禁用水平方向滾動


 

scroll.scrollHorizontal = false


 

現(xiàn)在原型中的第三個界面應(yīng)該能滾動了。

39125768cfec0000018c1b20c83c.jpg


 

為了讓這個 framer原型更具真實(shí),現(xiàn)在來做汽車的移動。


 

創(chuàng)建一個小汽車在一條路徑上通過轉(zhuǎn)彎到另一條路徑??梢酝ㄟ^改變 x, y的坐標(biāo)實(shí)現(xiàn)移動,通過轉(zhuǎn)動角度來變化路徑,讓它看起來像沿著路徑運(yùn)動。


 

moveCarDown= new Animation

    layer: uber.delorean

    properties:

        x: 130

        y: 95

    time: 20


 

moveCarLeft= new Animation

    layer: uber.delorean

    properties:

        rotation: -100

        x: 125

        y: 125

    time: 10    


 

通過監(jiān)聽moveCarDown動畫的結(jié)束事件來開始 moveCarLeft動畫建立一個動畫序列。


 

moveCarDown.on Events.AnimationEnd, ->

    moveCarLeft.start()


 

這里需要在開始 moveCarDown 動畫開始的時候,開始 enRouteRotate動畫


 

requestingPulse.on Events.AnimationEnd, ->

    requestingCount++

    if requestingCount is 3

        uber.enroute.opacity = .3

        uber.requesting.visible = false

        uber.enroute.visible = true

        uber.enroute.animate    

            properties:

                opacity: 1

        

        enRouteRotate.start()

        moveCarDown.start()


 

小汽車已經(jīng)沿著路徑移動了,為了展示,只制作了簡短的 gif動畫避免gif過大,效果如下:

1bff5768d02d0000018c1b0690de.jpg

最后,在5秒之后更新標(biāo)簽 ““En Route”為“Arriving Now” ,這里用延時函數(shù) delay 函數(shù)實(shí)現(xiàn),它的意思是在操作執(zhí)行之前等待幾秒。


 

moveCarDown.start()

        Utils.delay 5, ->


 

在5秒之后,隱藏當(dāng)前的標(biāo)簽顯示需要展示的標(biāo)簽,這里都用到了 visible屬性。


 

 Utils.delay 5, ->

            uber.enRouteTitle.visible = false

            uber.arrivingNowTitle.visible = true


 

恭喜您,我們在 framer中已經(jīng)實(shí)現(xiàn)he Uber Apple Watch app的效果了。

0ec25768d0530000012e7e860fea.jpg 


5
評論區(qū)(0)
正在加載評論...