貝塞爾風暴 - 超炫GABottleLoading效果

hp1227hp 7年前發布 | 8K 次閱讀 貝塞爾曲線 Android開發 移動開發

談到貝塞爾曲線,很多人會覺得高逼格、復雜、頭疼,實則不然,貝塞爾曲線經過android封裝,已經顯得嬌俏可愛,簡單好用,之前一些紅極一時的效果也均是由其打造,比如QQ的“一鍵退潮”效果、電子書曲面翻頁效果...... 現在咱們就用貝塞爾曲線一起從0到1打造一個擁有極致體驗、清秀靈動的GABottleLoading效果;

好了,不多吹NB了,老規矩先上一個原始效果圖:

看到這個效果,估計有人開噴:

“我擦,聽你吹半天NB,這個效果老子兩年前就看過了,github上早有了,垃圾......”

此時,沉穩優雅、帥氣逼人的GA哥在github上通過關鍵字搜索,兩個實現赫然出現在我的面前,看來天不助我,然后通過查看他們的實現,發現其中一個實現的很棒,老實說GA哥都沒有信心實現到如此完美,but看過之后發現他是直接加載gif,fuck, too young, too simple, 另一個呢?通過代碼實現,現在讓我們瞻仰下他實現的效果:

從效果上來看,基本實現了瓶身、波紋晃動,但真正復雜的氣泡與動態并傾斜的水面的脫離過程卻并未實現,而這才是GA哥感興趣的地方,此時天空響起一聲驚雷,GA哥閃亮登場;

首先,讓我們一起分解下這個動效,簡單來看,該效果可以分成以下幾個部分:

1.水滴從水面彈出和融入;

2.水面的波動;

3.瓶身的繪制;

接下來,咱們一起從以上三個內容逐個處理:

一、水滴從水面彈出和融入

正式分析之前,請和GA哥一起通過一個慢鏡頭看看其中一個水滴脫離水面的過程;

我擦,不看不知道,沒想到過程如此細膩!

是不是突然感覺這個動效沒那么簡單了?是不是有點難度了?尤其是水滴離開水面的過程中,水面還在不斷的變動,而整個水滴彈出和融入的過程都需要和水面柔和爽朗的連接;

俗話說,“擒賊先擒王”,咱們第一步就來搞定水滴的粘連出入過程!

首先我們來看一下過程分解圖(請關注左邊的水滴):

由上圖可以觀察到,到(4)的時候,水滴已經完全脫離了水面,只不過存在一定的粘連(由于水的張力);

接下來我們分析下水滴脫離水面的過程,為了更好的說明,將水面簡化為一個靜態的斜面,這樣更加直觀;

那么原始模型如下圖,其中斜線代表水面,圓代表水滴,是不是很簡單?

接下來我們需要考慮,如何處理水滴和水面的粘連效果,標題既然叫做貝塞爾曲線打造極致GABottleLoading效果,咱們肯定是使用貝塞爾曲線這一神器了,既然使用貝塞爾曲線,那么不用多說,就需要考慮起始點、終點、控制點這些核心數據;

從效果來看,起始點咱們可以直接從水滴上取,然而具體取到何處呢?咱們可以以水滴冒出水面的高度為基準,然后定義一個適當比例,以該比例計算具體數據點;

既然起始點在水滴上,那么終點毋庸置疑在水面上,具體取于何處呢?咱們可以采用如下方式(至于為何要這么取則是GA哥的思路):

使用一個矩形框框住水滴區域,使水滴距離左右兩邊 L1、L2,并且L1 == L2 ;

此時矩形框與水面形成交點w1、w2,咱們可以直接選取如圖所示w1、w2作為兩個終點,這兩個點即表示水滴由于張力而形成的拖尾和水面的接觸點;

經過以上思路,咱們畫出以下圖示:

看上面這張圖,其中L3為水面上點w1和w2的連接線,L4為經過圓心并且和L3垂直的直線,wd為L3與L4的交點,,Ct為圓最頂端數據點,C1、C2為垂直于L4的L5與圓環的交點;

咱們將輔助線都去掉,那么就得到如下的圖:

在圖上,C1、C2為起始點,W1、W2為終點;

好了,起始點、終點咱們定下了確定的方法,控制點呢?

且繼續看下圖;

圖中L6、L9分別為點w1及w2所在的水面的切線,L7、L8分別為C1及C2處的切線,q1為L6與L7的交點、q2為L8與L9的交點,q1與q2則為咱們找的兩個控制點;

到此,包括起始點、終點、控制點在內的貝塞爾曲線所需的核心數據咱們就都找到了,如下圖所示的6個點;

6個點、6個點、6個點,重要的事情說三遍......

然后咱們利用以上6個點繪制兩條二階貝塞爾曲線,形成相應拖尾粘連效果,具體效果圖如下:

我們把不需要的點去除,并填充上顏色,看看最后的效果:

那么這部分整體效果的結果如何?請看!

這個不夠直觀?那讓我們加上輔助點,請看!

  • 圓上的白色的點從左往右分別是c1、c2,分別表示拖尾與圓的接觸點,即貝塞爾曲線的起始點;
  • 圓兩側兩側紅色的點從左往右為分別為w1、w2,表示拖尾與水面的接觸點,即貝塞爾曲線的終點;
  • 藍色點從左往右分別為q1、q2,分別表示左右兩側的控制點;

最后,圓完全脫離水面如下圖:

圓拖著拖尾上移:

最后拖尾斷裂:

最后水滴完全脫離,水面恢復平靜:

讓我們一起來看看整個過程:

ok,到此,水滴從水面彈出和融入的思路分析就此結束;

二、水面的波動分析

同樣,咱們先看下原始效果圖:

貝塞爾風暴 - 超炫GABottleLoading效果

github上已實現效果圖:

貝塞爾風暴 - 超炫GABottleLoading效果

沒有對比就沒有傷害,看起來是不是覺得原始效果圖要柔和自然很多?那么到底是什么原因呢?GA哥分析主要是以下兩點原因:

  • 1.波動效果,原效果圖是一個減速過程,當水波達到最高點的時候速度變為了0,而對比圖是一直勻速的過程;
  • 2.上面流動的水和下面靜止的水的連接處理有差異;

當然,以GA哥的尿性肯定是以原效果圖為目標,而當GA哥在PS中采用三階貝塞爾曲線去擬合的時候,發現還是存在一定的瑕疵,不能完全的擬合上;

最終,最右邊的連接弧度采用上圖所示數據作為參數,實現的效果如下:

我擦,連接處不夠柔順,此時GA哥采用了以下處理方案;

將波動的水面抬高,和底部靜止的水面保持一定的距離,然后采用二階貝塞爾曲線將兩者的連接處進行連接:

恩,上圖的效果還是可以接受的,讓我們看看動起來什么效果:

  • 作者注:恩,此時如GA哥的秀發般飄逸了! - GAStudio哥

三、瓶身的繪制

瓶身繪制就是一個字——"扣",扣細節,然后達到各個接觸點比較完美的連接;

貝塞爾風暴 - 超炫GABottleLoading效果

讓我們從左半部分的上方開始講起。

瓶口處的的彎角,一開始GA哥也是認為是一個半圓(180度),然后再連接直線。然而這樣做效果不是很好,所以GA哥采用四分之一圓環(90度),然后連接45度的直線,最后連接垂直的瓶嘴直線,效果如下圖:

  • 路人甲:納尼?怎么有這么明顯的棱角?作為細致的GA哥,依舊沒有放過這個細節。
  • 路人乙:敢問GA哥有什么有效的方案?使用Paint.Cap.ROUND?
  • GA哥:No, No, No, Paint.Cap.ROUND 只對line的頭部有效,GA哥采用了將Paint的PathEffect設置成了CornerPathEffect,那么就會將直線和直線間的連接處,自動做了圓滑處理。

那么效果如何呢?請看下圖:

臥槽,好帥,好柔滑有木有!

此外, 瓶身連接處 (如下圖紅色標注處)也是需要注意的,要么計算準確,完美的連接;要么索性有一點缺口,采用arcTo繪制瓶身,此時缺口會自動連接上直線,再加上之前配置的CornerPathEffect,就會使得該處顯得自然:

接著 瓶身 采用圓弧繪制,從多少到多少角度都需要進行計算;

最后 底部 采用直線直接連接;

  • GA哥: 恩,你們是不是覺得GA哥會說,右半部分和左半部分采用一樣的思路?
  • 路人甲: 難道不是嗎?難道GA哥有啥高招?
  • GA哥: 恩,GA哥這個人比較懶,所以什么事都想偷懶;

恩,我們都不用仔細觀察,這個瓶子是 左右對稱 的!所以直接反轉過來就行了哇!

關鍵代碼如下:

// Generate the right path Camera camera = new Camera(); Matrix matrix = new Matrix(); camera.save(); camera.rotateY(HALF_FULL_ANGLE); camera.getMatrix(matrix); camera.restore(); matrix.preTranslate(-mViewRectF.centerX(), -mViewRectF.centerY()); matrix.postTranslate(mViewRectF.centerX(), mViewRectF.centerY()); Path rightBottlePath = new Path(); rightBottlePath.addPath(mBottlePath); mBottlePath.addPath(rightBottlePath, matrix);

總結

  • GA哥:總結?總結啥呢?
  • 路人甲:看看效果唄,看你吹了這么久,哈哈!
  • 路人乙:贊同樓上的;
  • 路人丙:贊同樓上的;
  • 路人丁:贊同樓上的;
  • ...
  • GA哥:盛情難卻哇,那就獻丑了!

最后,附上GAStudio技術交流群和Github,喜歡的話歡迎follow和star:

 

來自:http://www.jianshu.com/p/93b0d948abf8

 

 本文由用戶 hp1227hp 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!