當前位置:
首頁 > 最新 > 召喚,光能使者-玩轉PathMeasure

召喚,光能使者-玩轉PathMeasure

作者博客

http://www.jianshu.com/u/975e915e131b

文章目錄

前言

PathMeasure

動畫拆解

代碼實現

前言

首先我們來回顧一下童年吧~~90後滿滿的記憶

GIF/1651K

小時候總是幻想著自己能變身,今天我們就來用代碼實現變身的第一步吧,動畫繪製一個魔法陣magic_circle~~

靜態圖片比較容易,我們用 Path 設置好路徑,然後再 canvas.drawPath 即可,但是靜態的也太 low 了一點,我們要讓它動起來。

GIF/64K

效果看完了,不會寫的童鞋肯定已經懵逼了,會的童鞋可以出門左拐了,因為實現實在太簡單。

好了,在開始擼代碼之前,我們先來學習一個類 PathMeasure。我們的光能使者陣就是是基於這個類的兩個方法擼出來的。

1

PathMeasure

這個類的 class 注釋就一個版權說明,醬紫~

踏馬的,Google 工程師都偷懶了,注釋都不寫。。。幸好這個類只有一百多行代碼,那我們就自己看吧

Public constructors

PathMeasure 創建一個空的 pathmeasure 對象

PathMeasure(Path path,boolean forceClosed)創建一個帶 path 參數的 PathMeasure,forceClosed控制 path 是否自動閉合

Public methods

getLength() 返回當前 Path 的總長度。

getMatrix(float distance, Matrix matrix, int flags)

getPosTan(float distance, float[] pos, float[] tan)獲取distance長度的 point 值給 pos,point 點的正切值給 tan。

getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo) 獲取 path 的一個片段,即startD到 stopD 的線段,輔助給 dst。

isClosed() 是否自動閉合

nextContour() 移動到下一條曲線。如果 path 中含有不連續的線條,getLength、getPosTan等方法之會在第一條線上運行,需要使用這個方法跳到第二條線

setPath(Path path, boolean forceClosed)

是不是很簡單,就這麼幾個方法,現在去畫光能使者陣有思路了么~~

接下來為了便於大家理解,我們再來簡單回顧一下 path 的 api,因為靜態的光能使者陣是需要 path 去繪製的。

Path

就這樣簡單回顧一下吧,具體玩法可以參考 Hencoder 的 bolg

2

動畫拆解

好了,準備工作完成,我們開始擼代碼

第一步,繪製靜態的光能使者陣

首先繪製兩個圓,然後就是中間的六角星(其實仔細看就是兩個三角形)。

都是很簡單的方法,同學們動手去畫的時候可能會遇到一個這樣的問題,就是三角形的三個點不好取。其實很簡單,直接在圓上取0,1/3,2/3長度的點即可,剛剛我們不是說了 PathMeasure 的方法么,用getPosTan就可以實現。

第二步,讓光能使者陣動起來

這裡我們把這個動畫效果分成三個階段吧。

第一階段,繪製兩個圓

GIF/53K

如上圖所示,這裡兩個圓是慢慢繪製出來的, 圓的 path 很容易繪製出來,這裡我就不講了,然後PathMeasure的getLength可以獲取 path 總的長度,getSegment可以獲取某個點到某個點的 Path。因此一個 ValueAnimator 就可以解決從0到100%長度的過程,具體實現看後面的代碼。

然後問題來了,path畫出來的圓的起點在哪裡?怎麼控制兩個圓開始繪製的角度不一樣。有同學可能想到了旋轉90°再畫第二個圓,當然這種方式是可以實現的,但是由於後面的三角形也需要旋轉,這裡我們就不用 path 畫圓了,用 path 添加一個正方形 Rect 的圓弧也是一個圓,然後我們的圓弧可以控制開始的角度,弧度。

然後變成這樣了

GIF/72K

WTF?角度怎麼不對了,我明明設置的開始角度的呀

innerCircle.addArc(innerRect, 150, -360);

outerCircle.addArc(outerRect, 60, -360);

最後有個大牛說你的圓變成閉環了,PathMeasure 找不到開始點,用了默認的。你把360度改成359.9讓他不是一個閉環的圓就行了。

第二階段,兩個點在圓裡面彈射

GIF/26K

看起來好像還要幹什麼碰撞反彈之類的事,一副高科技的樣子,其實不是的。

軌跡就是兩個三角形,怎麼讓兩條線跟著三角形走呢,而且走的時候還要不段變化長度。

剛剛第一步我們用 ValueAnimator 來控制一個圓從0到100%的過程,

pathMeasure.getSegment(0, distance * pathMeasure.getLength(), drawPath, true);

不斷截取起點到*%長度的 path 賦值給drawPath。

從里是從起點開始截取,那麼我們不從起點開始截取,從當前點附近開始截取不就行了嗎,哈哈哈哈~so easy

float stopD = distance * pathMeasure.getLength();

float startD = stopD - (0.5f - Math.abs(0.5f - distance)) * 200;

pathMeasure.getSegment(startD, stopD, drawPath, true);

第三階段繪製兩個三角形

GIF/23K

其實兩個三角形就是第二步的運動軌跡,也是就是說直接用第階段的 Path 即可,然後再用第一階段一樣的辦法就可以實現效果。

3

代碼實現

乾貨推薦

點擊展開全文

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 碼蛋 的精彩文章:

技術分享 你不是一個人
不管出彩還是出局,要管得住初心
如何在移動開發者的寒冬中破冰而出?
Android圖文混排實現方式詳解
你知道一次HTTP請求響應涉及了哪些知識嗎?

TAG:碼蛋 |