中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android 貝塞爾曲線實戰之鯨云特效

發布時間:2020-07-12 00:30:04 來源:網絡 閱讀:150 作者:個推 欄目:移動開發

作者:哈哈將 -個推 Android 高級開發工程師

前言

APP開發市場已經告別“野蠻生長”時代,人們不再滿足于APP外形創新,而將目光轉向全方面的用戶體驗上。在這過程中,動效化作為移動互聯網產品的新趨勢,如何實現酷炫絲滑的動畫效果已然成為開發者們的新課題。實現方式其實很簡單。本文將為你剖析理論基礎以及具體應用。看完這篇文章,你的App也可以達到酷炫吊炸天的動畫效果。

先看兩個例子:

1. 手機 QQ 未讀消息紅點拖拽效果。

Android 貝塞爾曲線實戰之鯨云特效

2. 小說閱讀 APP 的翻頁效果。

Android 貝塞爾曲線實戰之鯨云特效

簡介

在開始實戰之前,我們還是先了解下理論基礎。動畫的終極武器就是貝塞爾曲線了。它是一條光滑的曲線,依據四個位置任意的點坐標繪制而成。1962年,法國工程師皮埃爾·貝塞爾(Pierre Bézier)率先研究出這種矢量繪制曲線的方法并給出了詳細的計算公式,應用于汽車的主體設計。因此,人們將按照此種公式繪制的曲線命名為貝塞爾曲線。

核心思想

貝塞爾曲線是計算機圖形學中運用得最多的參數曲線之一。它通過控制曲線上的四個點(起始點、終止點以及兩個相互分離的中間點)來創造、編輯圖形。其中起重要作用的是位于曲線中央的控制線。這條線是虛擬的,中間與貝塞爾曲線交叉,兩端是控制端點。移動兩端的端點時貝塞爾曲線可以改變曲線的曲率(彎曲的程度);移動中間點(也就是移動虛擬的控制線)時,貝塞爾曲線在起始點和終止點鎖定的情況下做均勻移動。注意:貝塞爾曲線上的所有控制點、節點均可編輯。

原理

這里面有個通用公式,這個公式已經有前輩幫我們總結好了。

Android 貝塞爾曲線實戰之鯨云特效

其中 P0 為起點,Pn 為中點,Pi 為控制點。

一階貝塞爾曲線

Android 貝塞爾曲線實戰之鯨云特效

一階這個比較簡單,因為沒有在網上找到可以直接輸入數學公式的工具,就手工推導了下。一階這個比較簡單,因為沒有在網上找到可以直接輸入數學公式的工具,就手工推導了下。


Android 貝塞爾曲線實戰之鯨云特效

最后的公式為 B(t)=(1-t)Po+tP1,t->[0,1]


二階貝塞爾曲線

先看動畫效果。


Android 貝塞爾曲線實戰之鯨云特效

關注紅線部分,這條線就是我們單位時間內運行的貝塞爾曲線效果圖。這條紅線實際上是由無數個點組成,隨著 t 的不斷變化,紅線的轉換過程非常的順滑。

Android 貝塞爾曲線實戰之鯨云特效


Android 貝塞爾曲線實戰之鯨云特效

最后得到的公式如下:


Android 貝塞爾曲線實戰之鯨云特效

貝塞爾曲線的繪制,無論多少階(一階除外),均需要逐級降階,最終降至一階。在 “二階貝塞爾曲線解析” 這段文字中,從 第一步 到 第二步 的過程就是在降階。貝塞爾曲線最終的路徑是由 一階基線 上游走的紅色小點形成的。

三階貝塞爾曲線

有了二階的推導過程,三階的推導就容易多啦。由于篇幅限制,推導過程這里不再展開,大家有興趣的話可以自行推導下。


Android 貝塞爾曲線實戰之鯨云特效

最后的紅色曲線是由藍色一階曲線獲得的,而藍色一階曲線又是由綠色一階曲線獲得,最后的綠色一階曲線則是最外的 P0,P1,P2,P3構成的。動畫效果為:

Android 貝塞爾曲線實戰之鯨云特效

四階貝塞爾曲線

Android 貝塞爾曲線實戰之鯨云特效

五階貝塞爾曲線

Android 貝塞爾曲線實戰之鯨云特效

結論?我們發現原來貝塞爾曲線上的點與高數中二項式展開一樣,對于每個線段上的點經過控制點進行切面操作,而連續的兩點之間是無限接近的,所以在繪制的過程中會出現非常絲滑地過度。

貝塞爾曲線在 Android 上的使用

在Android 中使用貝塞爾曲線比較簡單,Android 已經內置了貝塞爾曲線的 API,開發者可以直接予以調用。主要有兩個 API 。

quadTo

Android 貝塞爾曲線實戰之鯨云特效

其中 (startX,startY) 為起點,(endX,endY)為終點,而 (eventX,eventY)即為控制點了。

cubicTo

Android 貝塞爾曲線實戰之鯨云特效

調用此方法即可畫出一條三階貝塞爾曲線。(startX,startY)為起點,(endX,endY)為終點,而(leftX,leftY)與(rightX,rightY) 為兩個控制點了。

多階貝塞爾曲線:?Android 系統最高只能畫出三階的貝塞爾曲線,那么想畫出更高階的怎么辦呢?其實也很簡單。如果真的需要使用高階的曲線,可以進行人工降階,降階到 3 級即可。

實戰

終于到實戰環節了,該環節共有兩個demo。一個是貝塞爾曲線擬圓效果,另一個是仿網易云音樂里面的鯨云效果。

效果實現1:以貝塞爾曲線畫圓為例

前文總結了貝塞爾曲線的通用公式。在網上瀏覽資料的過程中我們發現有這么一個公式:(4/3)tan(π/(2n)),其意義是由n段三階貝塞爾曲線擬合圓形時,曲線端點到該端點最近的控制點的最佳距離是(4/3)tan(π/(2n))。大家感興趣的話可以自行推導。推導過程并不復雜,因為貝塞爾曲線有個重要的性質,即曲線方程中t=0.5時的點一定落在圓弧上。只需要把坐標系帶入到三階方程式即可。


Android 貝塞爾曲線實戰之鯨云特效

最后得知當 t=0.5,根據圓形方程式 X^2+Y^2=R^2 ,得到h=(4/3)(sqrt(2)-1) ≈ 0.552284749831 。有了上述的理論基礎,再去畫圓就非常的輕松,我們先在草稿紙中得到這么一個模型。


Android 貝塞爾曲線實戰之鯨云特效

根據上圖,這個圓是由 4 段三階貝塞爾曲線構成的,分別是 P0->P3,P3->P6,P6->P9,P9->P11。三階貝塞爾曲線的構圖是 Android 內置的,我們直接調用API 即可,核心代碼如下:


publicHeartView(Context context, @Nullable AttributeSet attrs,intdefStyleAttr){? ? ? ? super(context, attrs, defStyleAttr);? ? ? ? init(context)? ? }@Overrideprotectedvoidinit(Context context){mPaint =newPaint();mPaint.setAntiAlias(true);? ? ? ? mPaint.setColor(Color.RED);? ? ? ? mPaint.setStyle(Paint.Style.FILL);mPath =newPath();//繪制 12 個點。mCurPointList =newArrayList<>();mCurPointList.add(newPointF(0, dpToPx(-89)));mCurPointList.add(newPointF(dpToPx(50), dpToPx(-89)));mCurPointList.add(newPointF(dpToPx(90), dpToPx(-49)));mCurPointList.add(newPointF(dpToPx(90),0));mCurPointList.add(newPointF(dpToPx(90), dpToPx(50)));mCurPointList.add(newPointF(dpToPx(50), dpToPx(90)));mCurPointList.add(newPointF(0, dpToPx(90)));mCurPointList.add(newPointF(dpToPx(-49), dpToPx(90)));mCurPointList.add(newPointF(dpToPx(-89), dpToPx(50)));mCurPointList.add(newPointF(dpToPx(-89),0));mCurPointList.add(newPointF(dpToPx(-89), dpToPx(-49)));mCurPointList.add(newPointF(dpToPx(-49), dpToPx(-89)));? ? }@OverrideprotectedvoidonDraw(Canvas canvas){? ? ? ? drawCoordinate(canvas);canvas.translate(mWidth /2, mHeight /2);? ? ? ? mPath.reset();for(inti =0; i <4; i++) {if(i ==0) {mPath.moveTo(mCurPointList.get(i *3).x, mCurPointList.get(i *3).y);}else{mPath.lineTo(mCurPointList.get(i *3).x, mCurPointList.get(i *3).y);? ? ? ? ? ? }intendPointIndex;if(i ==3) {endPointIndex =0;}else{endPointIndex = i *3+3;? ? ? ? ? ? }mPath.cubicTo(mCurPointList.get(i *3+1).x, mCurPointList.get(i *3+1).y,mCurPointList.get(i *3+2).x, mCurPointList.get(i *3+2).y,mCurPointList.get(endPointIndex).x, mCurPointList.get(endPointIndex).y);? ? ? ? }? ? ? ? canvas.drawPath(mPath, mPaint);? ? }}

成果展示


Android 貝塞爾曲線實戰之鯨云特效

效果實現2:以網易云音樂鯨云效果為例

Android 貝塞爾曲線實戰之鯨云特效

轉換成 GIF,圖片可能會有點失真,但并不妨礙具體實現思路。根據這個 GIF,我們發現有三點功能需要去完成:

1.背景色與歌曲圖片相搭配,隨圖片的變化而變化;

2.歌曲中間圖片是一張圓形圖片并且可以自動旋轉;

3.圖形外圈有動感 3D環繞效果。

第一點實現比較簡單。

第二點也不難。我們可以把一張圖片裁剪成圓形,也可以使用 GitHub 上現有的開源庫,再加上一個屬性動畫代碼。

publicvoidhandleRotate(){ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(ivShowPic,"rotation",0f,360f);objectAnimator.setDuration(20*1000);? ? ? ? objectAnimator.setRepeatMode(ValueAnimator.RESTART);objectAnimator.setInterpolator(newLinearInterpolator());objectAnimator.setRepeatCount(-1);? ? ? ? objectAnimator.start();? ? }

看下動感3D環繞效果即轉圈圈。

Android 貝塞爾曲線實戰之鯨云特效

第三點?如何做跳動旋律特效?!!先不考慮前面兩點需求,我們逐步分析下跳動旋律特效。動態圖在文章開始部分已經看到了,我們建議先從靜態圖著手。


Android 貝塞爾曲線實戰之鯨云特效

我們猜測可能的實現思路(不代表官方實現思路):該動效外層一圈有 4 條線段在不規則地跳動,每條線的背后是一個圓,每個圓由 4 條貝塞爾曲線組成。

第一步?先畫個圓。我們只需要把畫筆的屬性設置成如下屬性,即可畫出一個空心圓。

Android 貝塞爾曲線實戰之鯨云特效

Android 貝塞爾曲線實戰之鯨云特效

為達到更順滑的環繞效果,我們需要不斷調試各條貝塞爾曲線的對應的兩個控制點。具體參數可根據業務場景來定。文中demo僅作參考。

第二步?上文我們分析過這個圓其實是由貝塞爾曲線組成的擬圓。在Android系統中是以每秒60幀為滿幀的,那么只要將1秒÷60幀,就能得出16毫秒(ms)/幀是滿幀的界限,即每幀快于16ms則為流暢。所以我們這邊的刷新頻率設定為每 80 毫秒刷新一次:

Android 貝塞爾曲線實戰之鯨云特效

得到的效果如下:

Android 貝塞爾曲線實戰之鯨云特效

第三步?雛形已經完成,后續我們的做法是再往上添加 2 個圓,看下 3 個圓是怎么樣的效果。

Android 貝塞爾曲線實戰之鯨云特效

第四步?最后一步當然是把前面兩點合在一起啦,合一起后就可以看下最終效果了:

Android 貝塞爾曲線實戰之鯨云特效

實際效果與預期效果會存在一定的差異,主要原因在于函數坐標以及畫筆的一些屬性問題。以上就是具體的實現思路,供大家參考。

總結

酷炫動畫的實現過程并沒有我們想象的那么復雜。其實,很多復雜特效都是由不同的動畫組合而成的,而絲滑般的動態效果則離不開貝塞爾曲線的應用。希望這篇文章可以幫助到想要做出酷炫絲滑的動態效果的你。

如何獲取實戰 Demo

關注【個推技術學院】微信公眾號

(微信號:getuitech)

回復關鍵詞“曲線

即可獲取仿鯨云特效動畫demo!

Android 貝塞爾曲線實戰之鯨云特效


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

高州市| 定兴县| 隆昌县| 蒙自县| 新和县| 宾阳县| 九江县| 高阳县| 鱼台县| 廊坊市| 泸定县| 馆陶县| 宣武区| 呼玛县| 宁国市| 象州县| 叙永县| 西乡县| 澳门| 土默特右旗| 英德市| 台湾省| 综艺| 中宁县| 酒泉市| 晋宁县| 遵义县| 平阴县| 台安县| 曲麻莱县| 蒙自县| 沈丘县| 临汾市| 平泉县| 延长县| 武冈市| 敖汉旗| 肇庆市| 晴隆县| 错那县| 太保市|