最近在學習CALayer相關動畫,然后某一天突然發現蘋果安裝app這動畫就很不錯啊,所以就想自己實現下。
具體效果如圖:
還是不試不知道一試嚇一跳啊,這看上去簡單的動畫沒我想象的那么簡單。
首先這個動畫分兩步:
一是中間的圓像時鐘一樣走一圈;
二是外面的大圓變大到包括整個圖片的大小;
首先是第一步:
這時候大圓外部跟小圓內部都是半透明的,小圓走過的部分會變成透明。
一開始我一直想用mask的方式來實現,結果試了老好久還是不行,就扔那兒了。
過了兩天再看它,發現其實自己想復雜了,從表面看的話,
第一部分的動畫是畫一個圓,然后用一個顏色填充它,中間就是畫圓的一部分然后填充,問題是這樣一點點走的動畫好難實現;
所以我就想如果是自己用筆畫的話要怎么辦?
然后發現用筆畫的話,只要用跟半徑一樣寬的線來畫就很easy了,畫多少就是多少,想停哪兒就停哪兒!
然后跟代碼一對照才恍然大悟,CAShapeLayer就有lineWidth這個屬性啊,也這么畫就很簡單了!
(這里需要注意CAShapeLayer計算fillColor的范圍時,是按照線的中心計算的,所以實際在代碼中線寬是半徑2倍)
透明的問題也是一樣,根本不用什么mask,畫的時候是覆蓋上去,那畫反過來不就是一點點露出來了嘛?。?!
放到代碼里的話,讓strokeEnd從1變到0就ok了。 (這里需要注意方向的問題,貝塞爾曲線有取反方向的方法,設置path的時候注意)
那剩下的問題是:怎么畫一個中間圓透明,圓與邊框之間半透明的圖形出來?
我首先想到的是。。。。做個圖片。。。然后試了試,果然可以!不過第二步的動畫沒法做了。。。
所以還是得用CAShapeLayer自己畫。。。
這里經春哥指點才解決了這個問題,用到了一個比較高端的參數,就是CAShapeLayer的fillRule參數。
有兩個可選值kCAFillRuleEvenOdd 和 kCAFillRuleNonZero
大致是:
nonzero字面意思是“非零”。按該規則,要判斷一個點是否在圖形內,從該點作任意方向的一條射線,然后檢測射線與圖形路徑的交點情況。從0開始計數,路徑從左向右穿過射線則計數加1,從右向左穿過射線則計數減1。得出計數結果后,如果結果是0,則認為點在圖形外部,否則認為在內部。下圖演示了nonzero規則:

evenodd字面意思是“奇偶”。按該規則,要判斷一個點是否在圖形內,從該點作任意方向的一條射線,然后檢測射線與圖形路徑的交點的數量。如果結果是奇數則認為點在內部,是偶數則認為點在外部。下圖演示了evenodd 規則:
具體就是先畫一個矩形,然后再用 appendPath方法添加一個圓進去作為整個CAShapeLayer的path;(也可以用 moveToPoint方法);
利用fillRule讓它圓內部透明,外部半透明。
然后把這個layer add 上去就可以了。
剩下的就是一個stokeEnd的動畫,就簡單了。
第二步:讓大圓的半徑變大
這個只是個path動畫,這里的大圓是上面第一步中最后那個方法畫出來的,只需要設置path為最終的大小就可以了,也比較簡單
還有一些細節見代碼注釋;