1. 程式人生 > >一個絢麗的loading動效分析與實現!

一個絢麗的loading動效分析與實現!



         尊重原創,歡迎轉載,轉載請註明: FROM  GA_studio   http://blog.csdn.net/tianjian4592


       前兩天我們這邊的頭兒給我說,有個 gif 動效很不錯,可以考慮用來做專案裡的loading,問我能不能實現,看了下效果確實不錯,也還比較有新意,複雜度也不是非常高,所以就花時間給做了,我們先一起看下原gif圖效果:




從效果上看,我們需要考慮以下幾個問題:

1.葉子的隨機產生;

2.葉子隨著一條正餘弦曲線移動;

3.葉子在移動的時候旋轉,旋轉方向隨機,正時針或逆時針;

4.葉子遇到進度條,似乎是融合進入;

5.葉子不能超出最左邊的弧角;

7.葉子飄出時的角度不是一致,走的曲線的振幅也有差別,否則太有規律性,缺乏美感;


總的看起來,需要注意和麻煩的地方主要是以上幾點,當然還有一些細節問題,比如最左邊是圓弧等等;

那接下來我們將效果進行分解,然後逐個擊破:

整個效果來說,我們需要的圖主要是飛動的小葉子和右邊旋轉的風扇,其他的部分都可以用色值進行繪製,當然我們為了方便,就連底部框一起切了;

先從gif 圖裡把飛動的小葉子和右邊旋轉的風扇、底部框摳出來,小葉子圖如下:


                                          


我們需要處理的主要有兩個部分:

1. 隨著進度往前繪製的進度條;

2. 不斷飛出來的小葉片;


我們先處理第一部分 - 隨著進度往前繪製的進度條:

進度條的位置根據外層傳入的 progress 進行計算,可以分為圖中 1、2、3 三個階段:



1. 當progress 較小,算出的當前距離還在弧形以內時,需要繪製如圖所示 1 區域的弧形,其餘部分用白色填充;

2. 當 progress 算出的距離到2時,需要繪製棕色半圓弧形,其餘部分用白色矩形填充;

3. 當 progress 算出的距離到3 時,需要繪製棕色半圓弧形,棕色矩形,白色矩形;

4. 當 progress 算出的距離到頭時,需要繪製棕色半圓弧形,棕色矩形;(可以合併到3中)


首先根據進度條的寬度和當前進度、總進度算出當前的位置:

[html]  view plain copy 在CODE上檢視程式碼片 派生到我的程式碼片
  1. //mProgressWidth為進度條的寬度,根據當前進度算出進度條的位置  
  2. mCurrentProgressPosition = mProgressWidth * mProgress / TOTAL_PROGRESS;  


然後按照上面的邏輯進行繪製,其中需要計算上圖中的紅色弧角角度,計算方法如下:

[html]  view plain copy 在CODE上檢視程式碼片 派生到我的程式碼片
  1. // 單邊角度  
  2. int angle = (int) Math.toDegrees(Math.acos((mArcRadius - mCurrentProgressPosition)/ (float) mArcRadius));  
Math.acos()  -反餘弦函式;

Math.toDegrees() - 弧度轉化為角度,Math.toRadians 角度轉化為弧度

所以圓弧的起始點為:

[html]  view plain copy 在CODE上檢視程式碼片 派生到我的程式碼片
  1. int startAngle = 180 - angle;  


圓弧劃過的角度為:

[html]  view plain copy 在CODE上檢視程式碼片 派生到我的程式碼片
  1. 2 * angle  


這一塊的程式碼如下:

[html]  view plain copy 在CODE上檢視程式碼片 派生到我的程式碼片
  1. // mProgressWidth為進度條的寬度,根據當前進度算出進度條的位置  
  2. mCurrentProgressPosition = mProgressWidth * mProgress / TOTAL_PROGRESS;  
  3. // 即當前位置在圖中所示1範圍內  
  4. if (mCurrentProgressPosition < mArcRadius) {  
  5.     Log.i(TAG, "mProgress = " + mProgress + "---mCurrentProgressPosition = "  
  6.             + mCurrentProgressPosition  
  7.             + "--mArcProgressWidth" + mArcRadius);  
  8.     // 1.繪製白色ARC,繪製orange ARC  
  9.     // 2.繪製白色矩形  
  10.   
  11.     // 1.繪製白色ARC  
  12.     canvas.drawArc(mArcRectF, 90, 180, false, mWhitePaint);  
  13.   
  14.     // 2.繪製白色矩形  
  15.     mWhiteRectF.left = mArcRightLocation;  
  16.     canvas.drawRect(mWhiteRectF, mWhitePaint);  
  17.   
  18.     // 3.繪製棕色 ARC  
  19.     // 單邊角度  
  20.     int angle = (int) Math.toDegrees(Math.acos((mArcRadius - mCurrentProgressPosition)  
  21.             / (float) mArcRadius));  
  22.     // 起始的位置  
  23.     int startAngle = 180 - angle;  
  24.     // 掃過的角度  
  25.     int sweepAngle = 2 * angle;  
  26.     Log.i(TAG, "startAngle = " + startAngle);  
  27.     canvas.drawArc(mArcRectF, startAngle, sweepAngle, false, mOrangePaint);  
  28. } else {  
  29.     Log.i(TAG, "mProgress = " + mProgress + "---transfer-----mCurrentProgressPosition = "  
  30.             + mCurrentProgressPosition  
  31.             + "--mArcProgressWidth" + mArcRadius);  
  32.     // 1.繪製white RECT  
  33.     // 2.繪製Orange ARC  
  34.     // 3.繪製orange RECT  
  35.      
  36.     // 1.繪製white RECT  
  37.     mWhiteRectF.left = mCurrentProgressPosition;  
  38.     canvas.drawRect(mWhiteRectF, mWhitePaint);  
  39.       
  40.     // 2.繪製Orange ARC  
  41.     canvas.drawArc(mArcRectF, 90, 180, false, mOrangePaint);  
  42.     // 3.繪製orange RECT  
  43.     mOrangeRectF.left = mArcRightLocation;  
  44.     mOrangeRectF.right = mCurrentProgressPosition;  
  45.     canvas.drawRect(mOrangeRectF, mOrangePaint);  
  46.   
  47. }  


接下來再來看葉子部分:

首先根據效果情況基本確定出 曲線函式,標準函式方程為:y = A(wx+Q)+h,其中w影響週期,A影響振幅 ,週期T= 2 * Math.PI/w;

根據效果可以看出,週期大致為總進度長度,所以確定w=(float) ((float) 2 * Math.PI /mProgressWidth);


仔細觀察效果,我們可以發現,葉子飄動的過程中振幅不是完全一致的,產生一種錯落的效果,既然如此,我們給葉子定義一個Type,根據Type 確定不同的振幅;

我們建立一個葉子物件:

[html]  view plain copy 在CODE上檢視程式碼片 派生到我的程式碼片
  1. private class Leaf {  
  2.   
  3.      // 在繪製部分的位置  
  4.      float x, y;  
  5.      // 控制葉子飄動的幅度  
  6.      StartType type;  
  7.      // 旋轉角度  
  8.      int rotateAngle;  
  9.      // 旋轉方向--0代表順時針,1代表逆時針  
  10.      int rotateDirection;  
  11.      // 起始時間(ms)  
  12.      long startTime;  
  13.  }  

型別採用列舉進行定義,其實就是用來區分不同的振幅:

[html]  view plain copy 在CODE上檢視程式碼片 派生到我的程式碼片
  1. private enum StartType {  
  2.     LITTLE, MIDDLE, BIG  
  3. }  

建立一個LeafFactory類用於建立一個或多個葉子資訊:

[html]  view plain copy 在CODE上檢視程式碼片 派生到我的程式碼片
  1. private class LeafFactory {  
  2.     private static final int MAX_LEAFS = 6;  
  3.     Random random = new Random();  
  4.   
  5.     // 生成一個葉子資訊  
  6.     public Leaf generateLeaf() {  
  7.         Leaf leaf = new Leaf();  
  8.         int randomType = random.nextInt(3);  
  9.         // 隨時型別- 隨機振幅  
  10. 相關推薦

    一個絢麗loading分析實現

             尊重原創,歡迎轉載,轉載請註明: FROM  GA_studio   http://blog.csdn.net/tianjian4592

    Android 漂浮類分析實現

    注:因部分原因,本篇主要講解動效分析的思路,不提供原始碼下載,請見諒 ... ... 上一篇只講了Canvas中的drawBitmap方法,並且還說的這個方法好像很膩害、能做出很多牛逼效果的樣子,

    C++ 單鏈表基本操作分析與實現 連結串列   連結串列是一種物理儲存單元上非連續、非順序的儲存結構,資料元素的邏輯順序是通過連結串列中的指標連結次序實現的。連結串列由一系列結點(連結串列中每一個元素稱為結點)組成,結

    連結串列   連結串列是一種物理儲存單元上非連續、非順序的儲存結構,資料元素的邏輯順序是通過連結串列中的指標連結次序實現的。連結串列由一系列結點(連結串列中每一個元素稱為結點)組成,結點可以在執行時動態生成。每個結點包括兩個部分:一個是儲存資料元素的資料域,另一個是儲存下一個結點地址的指標域。 相比於線性表

    跳躍表的分析實現

    insert text 站點 avi 初始 解析 鏈接 solid water ----《大規模分布式存儲系統:原理解析與架構實戰》讀書筆記 在了解了 Bitcask存儲模型後,又開始研究LSM樹存儲引擎。LSM在實現的過程中使用了一個非常有意思的數

    Java排序算法分析實現:快排、冒泡排序、選擇排序、插入排序、歸並排序(二)

    第一個元素 spa insert 循環 冒泡排序 author 高級算法 ins -s 一、概述:   上篇博客介紹了常見簡單算法:冒泡排序、選擇排序和插入排序。本文介紹高級排序算法:快速排序和歸並排序。在開始介紹算法之前,首先介紹高級算法所需要的基礎知識:劃分、遞歸,並順

    信息摘要算法之五:HMAC算法分析實現

    UC str 就是 n) auth 如果 輸出 返回 digest MAC(Message Authentication Code,消息認證碼算法)是含有密鑰散列函數算法,兼容了MD和SHA算法的特性,並在此基礎上加上了密鑰。因此MAC算法也經常被稱作HMAC算法。 1、H

    信息摘要算法之六:HKDF算法分析實現

    .com 方式 ems class 偽隨機 不一定 urn 如果 生成 HKDF是一種特定的鍵衍生函數(KDF),即初始鍵控材料的功能,KDF從其中派生出一個或多個密碼強大的密鑰。在此我們想要描述的是基於HMAC的HKDF。 1、HKDF概述 密鑰派生函數(KDF)是密碼系

    線程上下文類加載器分析實現

    背景 需求 clas htm ima ref 好的 技術分享 ren 在上一次【https://www.cnblogs.com/webor2006/p/9246850.html】分析源碼中發現有兩處設置線程上下文類加載器的代碼,如下: 因為它是非常重要的東東,所以

    數據壓縮算法---LZ77算法 的分析實現

    發現 如何 存儲 sse 而已 以及 turn 集合 alt LZ77簡介 Ziv和Lempel於1977年發表題為“順序數據壓縮的一個通用算法(A Universal Algorithm for Sequential Data Compression )”的論文,論文中描

    Android-貪吃蛇小遊戲-分析實現-Kotlin語言描述

    otl bject vid oid 小遊戲 同時 們的 http 畫布 Android-貪吃蛇小遊戲-分析與實現-Kotlin語言描述 Overview 本章的主要的內容是貪吃蛇小遊戲的分析和實現,關於實現的具體代碼可以在,文章底部的github的鏈接中找到。 整個遊戲通過

    (轉)從信息隱藏的一個需求看C++接口實現的分離

    要求 member 不可 所有 stack log virtual overflow int 原文地址https://blog.csdn.net/tonywearme/article/details/6926649 讓我們從stackoverflow上一個同學的問題來開始。

    手撕MyBatis底層原始碼分析實現

    MyBatis Hiberante 簡介 什麼是 MyBatis ? MyBatis 是一款優秀的持久層框架,它支援定製化 SQL、儲存過程以及高階對映。MyBatis 避免了幾乎所有的 JDBC 程式碼和手動設定引數以及獲取結果集。MyBatis 可以使用簡單

    十四 第三章再續 快速選擇SELECT演算法的深入分析實現

                                              十四、亦第三章再續:快速選擇SELECT演算法的深入分析與實現前言    經典演算法研究系列已經寫了十三個演算法,共計22篇文章(詳情,見這:十三個經典演算法研究與總結、目錄+索引),我很怕我自己不再把這個算法系列給繼續寫下去

    HTTP Live Streaming直播(iOS直播)技術分析實現

       不經意間發現,大半年沒寫部落格了,自覺汗顏。實則2012後半年(2018年注:這是我以前寫的文章,不要奇怪時間了),家中的事一樣接著一樣發生,實在是沒有時間。快過年了,總算忙裡偷閒,把最近的一些技術成果,總結成了文章,與大家分享。   前些日子,也是專案需要,花了一

    Linux I2C驅動分析實現--例子

    通過上篇《Linux I2C驅動分析與實現(二)》,我們對Linux子系統已經不陌生,那麼如何實現I2C驅動呢? 編寫客戶驅動的方法 在核心中有兩種方式的i2c客戶驅動的編寫方法,一種叫legacy傳統方式,另一種是newstyle方式. 前 一種legacy是一種舊式的方法,在2.

    智慧指標的分析實現

    一,為什麼要用智慧指標 在編寫c++程式的時候,讓我們最頭痛的問題就是記憶體洩露,也就是說 int* pt = new int; delete pt; 必須保證new和delete必須成對出現。作為程式猿,可以像使用普通變數一樣來使用指標,這個指標可以在恰當的時候被自動釋放,智慧指標

    DB Scan演算法的分析實現

        根據上面第二個資料集的簇的形狀比較怪異,分簇結果應該是連起來的屬於一個簇,但是k-means結果分出來很不如人意,所以這裡介紹一種新的聚類方法,此方法不同於上一個基於劃分的方法,基於劃分主要發現圓形或者球形簇;為了發現任意形狀的簇,用一個基於密度的聚類方法,這類方法將簇看做是資料空間中被低

    七種排序演算法的簡單分析實現

    {    int nFirst = nLow;    int nMid = (nLow + nHigh) /2;    int nSecond = nMid +1;    int* p = (int*)malloc(sizeof(int) * (nHigh - nLow +1));    int nIndex

    cc++相互呼叫機制分析實現

    c++通常被稱為Better c,多數是因為c++程式可以很簡單的呼叫c函式,語法上基本實現相容。最常用的呼叫方式就是c++模組呼叫c實現的dll匯出函式,很簡單的用法,使用extern "C"將c標頭檔案或者函式修飾下。 本文主要涉及到在c模組中如何呼叫c++函式,或者換個名字,extern

    iOS開發之蝦米音樂頻道選擇切換效果分析實現

    今天部落格的內容比較簡單,就是看一下蝦米音樂首頁中頻道選擇的一個動畫效果的實現。之前用mask寫過另外一種Tab切換的一種效果,網易雲音樂裡邊的一種Tab切換效果,詳情請移步於""。,下面會對效果進行分析,並且根據自己的理解去實現一個類似的頻道選擇切換效果。程式碼會在Github上進行分享,Demo實現時依然