真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Android怎么實現(xiàn)吹蠟燭動畫

這篇文章主要介紹“Android怎么實現(xiàn)吹蠟燭動畫”的相關(guān)知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“Android怎么實現(xiàn)吹蠟燭動畫”文章能幫助大家解決問題。

創(chuàng)新互聯(lián)是一家專注于網(wǎng)站設(shè)計制作、做網(wǎng)站與策劃設(shè)計,巫山網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)做網(wǎng)站,專注于網(wǎng)站建設(shè)10年,網(wǎng)設(shè)計領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:巫山等地區(qū)。巫山做網(wǎng)站價格咨詢:18980820575

一、簡介

我們來看這兩根萌萌的小蠟燭。

Android怎么實現(xiàn)吹蠟燭動畫

小蠟燭憋足氣把火焰燃起,一下被旁邊的哥們吹滅了 0^0  ,看起來還是萌氣十足的啊??粗鴪D大家應(yīng)該能想到應(yīng)該怎么實現(xiàn)了吧,自定義View!對了,但是具體要怎么把這個過程做好呢,跟著腳步一起來看一看吧。代碼稍微有點多,大家耐心觀看,有興趣的同學可以從我的GITHUB上clone下來,對著代碼看。

二、過程實現(xiàn)

蠟燭的繪制和動畫

  • 本著面向?qū)ο蟮乃枷?,很明顯這里就是兩個蠟燭嘛!既然是這樣那我們就定義一個蠟燭類具有蠟燭的基本屬性。 

Android怎么實現(xiàn)吹蠟燭動畫 

public abstract class ICandle {       //蠟燭底部左下坐標      protected int mCurX;      protected int mCurY;      //蠟燭寬高      protected int mCandleWidth;      protected int mCandleHeight;      //蠟燭左眼坐標      protected Point mEyeLPoint;      //蠟燭右眼坐標      protected Point mEyeRPoint;      //蠟燭眼睛半徑      protected int mEyeRadius;      //眼睛間隔距離      protected int mEyeDevide;      //身體顏色      protected int mCandleColor;      //是否停止動畫中      protected boolean mIsAnimStoping = false;      //蠟燭芯坐標      protected Point mCandlewickPoint;      public void initAnim(){      }      public void stopAnim(){      }      public void drawSelf(Canvas canvas){      }  }

對應(yīng)著這蠟燭還有代碼,那就一目了然了??赡苄枰忉尩膽?yīng)該就是下面的幾個方法了public void initAnim(),  stopAnim()初始化開始和結(jié)束動畫需要的數(shù)據(jù),小蠟燭將會實現(xiàn)這個方法,drawSelf(Canvas  canvas)把畫布傳進來然后蠟燭自己繪制自己。

現(xiàn)在就是讓我們來看一看小蠟燭身體內(nèi)部構(gòu)造的時候了,hiahiahiahia!

不對,和蠟燭生死相隨的還有火焰呢!先來看看火焰吧,等下小蠟燭還要燃燒自己呢。+10086s

Flame

  • 一樣先來一睹我們的富勒姆真容 

Android怎么實現(xiàn)吹蠟燭動畫 

Android怎么實現(xiàn)吹蠟燭動畫

好像也沒什么毛病,首先是里面的區(qū)域,就是Flame啦,外面的呢,就是Flame先生燃燒自己散發(fā)的人性之光和飄散的骨灰(手動抹眼淚)。

來看一下Flame的實現(xiàn)吧。我們一步步分析。

private static float CHANGE_FACTOR = 20;     private Paint mPaint;     private Path mPath;     //左下點坐標     private int mCurX;     private int mCurY;     //火焰寬度     private int mWidth;     //火焰高度     private int mHeight;     //記錄初始高度     private int mPreHeight;     //記錄初始寬度     private int mPreWidth;     //火焰頂部貝塞爾曲線控制點變化參數(shù)     private int mTopXFactor;     private int mTopYFactor;     //用于實現(xiàn)火焰的抖動     private Random mRandom;     //光環(huán)半徑     private int mHaloRadius;     //正在燃燒     private boolean mIsFiring;     //是否啟動停止動畫     private boolean mIsStopAnim = false;     private boolean mFlagStop = false;     private LinearGradient mLinearGradient;     private RadialGradient mRadialGradient;     private ValueAnimator mFlameAnimator;     private ValueAnimator mHaloAnimator;

參數(shù)就是這些了,主要是我們的動畫實現(xiàn)過程,也就是我們的屬性動畫ValueAnimator這里還有兩個渲染類不知道大家用過沒有,LinearGradient和RadialGradient不了解的同學可以直接點我的博文了解一下。LinearGradient繪制出了火焰,RadialGradient繪制除了發(fā)散的光芒。

初始化的過程我就不寫了,大家對這代碼看吧。那主要的就是小火焰的是怎么繪制出來的呢 show the code

mPaint.setStyle(Paint.Style.FILL);     mPaint.setShader(mLinearGradient);     mPath.reset();     mPath.moveTo(mCurX, mCurY);     mPath.quadTo(mCurX + mWidth / 2,             mCurY + mHeight / 3,             mCurX + mWidth, mCurY);     mPath.quadTo(mCurX + mWidth / 2 + ((1 - mRandom.nextFloat()) * CHANGE_FACTOR) + mTopXFactor,             mCurY - 2 * mHeight + mTopYFactor,             mCurX, mCurY);     canvas.drawPath(mPath, mPaint);

這就是火焰flame的繪制,可以看到這里用到了二次貝塞爾曲線的繪制,不太清楚貝塞爾曲線的同學也可以點這波浪Loading動畫(貝塞爾曲線)有簡單的介紹,當時是用在一個水波的view里面。這里的繪制是以前面那個圖里面的矩形為參照,我們再來看一下這個圖(當然是加強版hiahia)。

Android怎么實現(xiàn)吹蠟燭動畫

那為什么上面的x坐標還加了mRandom.nextFloat()) *  CHANGE_FACTOR呢?你想啊,火焰不是會左右晃動嗎,利用一個隨機來控制左右擺動咯。

mFlameAnimator = ValueAnimator.ofFloat(0, 4).setDuration(4000);     mFlameAnimator.setRepeatCount(ValueAnimator.INFINITE);     mFlameAnimator.addUpdateListener(                    new ValueAnimator.AnimatorUpdateListener() {         @Override         public void onAnimationUpdate(ValueAnimator animation) {             float zeroToOne = (float) animation.getAnimatedValue();             if (zeroToOne >= 1.0f && zeroToOne <= 1.2f) {                 //火焰燃起                 zeroToOne = 1.0f - 5 * (zeroToOne - 1.0f);//1-0                 mHeight = (int) (mPreHeight * (1 - zeroToOne));                 mIsFiring = true;             } else if (zeroToOne >= 3.5f) {                 if (mFlagStop) {                     mFlameAnimator.cancel();                     return;                 }                 //火焰被吹滅                 zeroToOne = 2 * (zeroToOne - 3.5f);//0-2                 mTopXFactor = (int) (-20 * zeroToOne);                 mTopYFactor = (int) (160 * zeroToOne);  /                    mWidth = (int) (mPreWidth * (1 -zeroToOne));                 mIsFiring = false;             }         }     });

在4秒的時間內(nèi),火焰進行了一系列活動,從下面隨著燈芯移上來,不斷的改變火焰的位置,分為了兩部分,火焰燃起和火焰熄滅,從代碼中可以看到,火焰燃起時mHeight慢慢變大,然后就是有了升起的過程辣,另外一個就是火焰被吹滅的時候,因為吹滅的時候火焰的高度肯定是保持之前的值,所以不需要改變,而是用了mTopXFactor和mTopYFactor這個兩個因子來控制火焰的位置。好了,既然火焰有了,蠟炬成灰淚始干啊,生命之光也該出場了。

光圈的繪制和動畫就相對簡單了

mPaint.setStyle(Paint.Style.STROKE);             mPaint.setStrokeWidth(5);             mPaint.setShader(mRadialGradient);             canvas.drawCircle(mCurX + mWidth / 2,                          mCurY - mHeight / 2, mHaloRadius, mPaint);             canvas.drawCircle(mCurX + mWidth / 2,                          mCurY - mHeight / 2, mHaloRadius + 5, mPaint);             canvas.drawCircle(mCurX + mWidth / 2,                          mCurY - mHeight / 2, mHaloRadius - 5, mPaint);

這里改變的只有一個參數(shù),mHaloRadius也就是光圈的半徑。但是不要忘了,其他參數(shù)同時也是在改變的呢,只不過是放在了mFlameAnimator里面。

好了介紹到這Flame的介紹完了,任重而道遠啊,寫了這么多卻還沒完結(jié),讓我想到一某位古人說過,不是我。

還未老死,就先累死

  • FireCandle

這名字有點奇怪,火燭,厲害了Word哥。前面已經(jīng)介紹過ICandle了,現(xiàn)在來看一下他的實現(xiàn)類,蠟燭兩兄弟之FireCandle。

初始化照例也就不說了,來看該有的變量。

private Paint mPaint;  //中心X坐標  private int mCenterX;  //記錄初始寬  private int mPreWidth;  //記錄初始高  private int mPreHeight;  //蠟燭芯旋轉(zhuǎn)角  private int mCandlewickDegrees = 0;  private Flame mFlame;  private boolean mIsFire = false;  private boolean mIsStateOnStart = false;  private boolean mIsStateOnEnd = false;  private boolean mFlagStop = false;  private ValueAnimator mCandlesAnimator;

命名還是挺規(guī)范的,應(yīng)該一看就知道是干嘛的。

我們還是來主要看繪制和屬性動畫的配合,繪制就不看了(光速打臉)。來看動畫。

mCandlesAnimator = ValueAnimator.ofFloat(0, 4).setDuration(4000);   mCandlesAnimator.addUpdateListener(                    new ValueAnimator.AnimatorUpdateListener() {       @Override       public void onAnimationUpdate(ValueAnimator animation) {           float zeroToOne = (float) animation.getAnimatedValue();           if (zeroToOne <= 1.0f) {               //蠟燭芯蓄力下拉               mIsFire = true;               mCandleWidth = mPreWidth + (int) (zeroToOne * 40);               mCandleHeight = mPreHeight - (int) (zeroToOne * 30);               mCandlewickDegrees = (int) (-60 + (180 + 60) * zeroToOne);               refreshEyePosition();           } else if (zeroToOne <= 2.0f) {               zeroToOne = zeroToOne - 1.0f;               //蠟燭芯上擺               if (zeroToOne <= 0.2f) {                   zeroToOne = 1.0f - 5 * zeroToOne;                   mIsFire = false;                   mCandleWidth = mPreWidth + (int) (zeroToOne * 40);                   mCandleHeight = mPreHeight - (int) (zeroToOne * 30);                   mCandlewickDegrees = (int) (180 * zeroToOne);               } else {                   if (mFlameStateListener != null && !mIsStateOnStart) {                       mFlameStateListener.flameStart();                       mIsStateOnStart = true;                   }                   mCandleWidth = mPreWidth;                   mCandleHeight = mPreHeight;                   mCandlewickDegrees = 0;                   if (mFlagStop) {                       mCandlesAnimator.cancel();                   }               }               refreshEyePosition();           } else if (zeroToOne >= 3.5f) {               //蠟燭芯被吹歪               zeroToOne = 2 * (zeroToOne - 3.5f);//0-1               mCandlewickDegrees = (int) (-60 * zeroToOne);               if (mFlameStateListener != null && !mIsStateOnEnd) {                   mFlameStateListener.flameEnd();                   mIsStateOnEnd = true;               }           }       }   });

這個就過程就有點多了,但是其實一點都不復(fù)雜,,首先我們看動畫里面的小蠟燭,一開始,他來了一個變胖紅臉深蹲,所以呢mCandleWidth是變大的,mCandleHeight是變小的,后面那個燈芯隨著深蹲來了一個大角度旋轉(zhuǎn),燈芯的如何旋轉(zhuǎn)大家也看到了,改變坐標系然后就可以了。用到了

canvas.rotate(mCandlewickDegrees, mCenterX, mCurY -  mCandleHeight);這個方法。上擺過程也是一樣的,就不多說了。refreshEyePosition();這個方法是改變眼睛位置的,兩個地方都用到了所以稍微獨立出來了。注意mIsFire這個變量,沒有火焰的時候就做其他繪制,比如說紅眼睛等等。好了好了,介紹到這,小蠟燭的部分就結(jié)束了。

SecCandle

大蠟燭,帥蠟燭鎮(zhèn)樓,實際的繪制和小蠟燭的就差不多了,這里就不解釋了。

Android怎么實現(xiàn)吹蠟燭動畫

共同繪制View和控制器

AnimControler

這個類的功能很簡單,繪制地板部分還有就是把計算后傳過來的高度寬度賦給兩支蠟燭,然后控制兩支蠟燭各自開始動畫。

mFirCandle = new FirCandle(mRelativeX + mWidth / 6, mRelativeY + mHeight);   mFirCandle.initCandle(mFirCandleWidth, mFirCandleHeight);   mFirCandle.initAnim();   mSecCandle = new SecCandle(mRelativeX + mWidth / 2, mRelativeY + mHeight);   mSecCandle.initCandle(mSecCandleWidth, mSecCandleHeight - 80);   mSecCandle.initAnim();

***的***,就是我們的View了

  • CandlesAnimView

//16ms刷新Canvas       mInvalidateAnimator = ValueAnimator.ofInt(0, 1).setDuration(16);       mInvalidateAnimator.setRepeatCount(ValueAnimator.INFINITE);       mInvalidateAnimator.addListener(new AnimatorListenerAdapter() {           @Override           public void onAnimationRepeat(Animator animation) {               invalidate();           }       });       mInvalidateAnimator.start();

這個屬性動畫履行的任務(wù)就是快速的刷新界面,是Candle的動畫能夠及時顯示。

@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {      super.onMeasure(widthMeasureSpec, heightMeasureSpec);      int width = measureDimension(WIDTH_DEFAULT * mDensity,                                widthMeasureSpec);      int height = measureDimension(HEIGHT_DEFAULT *mDensity,                                heightMeasureSpec);     setMeasuredDimension(width, height); }  public int measureDimension(int defaultSize, int measureSpec) {      int result;      int specMode = MeasureSpec.getMode(measureSpec);      int specSize = MeasureSpec.getSize(measureSpec);      if (specMode == MeasureSpec.EXACTLY) {         result = specSize;     } else {         result = defaultSize;          if (specMode == MeasureSpec.AT_MOST) {             result = Math.min(result, specSize);         }     }      return result; }  @Override protected void onDraw(Canvas canvas) {      if (!mIsInit) {         initConfig();         mIsInit = true;     }     mAnimControler.drawMyView(canvas); }

可以看到***在view里面調(diào)用了我們的控制器,把cavas傳過去了。

***的tip:大家有沒有發(fā)現(xiàn)每個動畫的duration都是一樣的。

關(guān)于“Android怎么實現(xiàn)吹蠟燭動畫”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識,可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,小編每天都會為大家更新不同的知識點。


當前標題:Android怎么實現(xiàn)吹蠟燭動畫
瀏覽地址:http://weahome.cn/article/gjhsoo.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部