package com.tomandjerry.coolanim.lib.pellet; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.graphics.Canvas; import android.graphics.Paint; import com.tomandjerry.coolanim.lib.Config; /** * Created by weicheng on 16/1/31. */ public class SecondPellet extends Pellet { //移动长度 private final int MOVE_MAX_LINTH = 120; //环绕线粗,应为AROUND_POINT_RADIUS*2; private final int LINE_STROKE_LENGTH = 8; //环绕行星(圆)半径 private final int AROUND_POINT_RADIUS = 4; //红球外半径,比最大半径稍微一点 private int mRedCirCleRadius = 50; //红球内半径 private int mRedCirStrokeFactor; //环绕线内点 private int mAroundLineInsideP = MAX_RADIUS_CIRCLE; //环绕线外点 private int mAroundLineOutsideP = MAX_RADIUS_CIRCLE; //环绕角度 private int mAroundLineDegrees = 0; //环绕偏离中心的坐标 private int mAroundPointY = 0; //这个方式待修改完善。 private int mFirYellowCirRadius; //黄球左偏移 private int mLineLeftOffset; //黄球右偏移 private int mLineRightOffset; private int mLineStrokeWidth = 120; private boolean mIsCirLineShow = true; //环绕行星可见性 private boolean mIsAroundPointV = false; //第二个黄色球 private int mSecYellowCirRadius; private Paint mPaint; private ValueAnimator firAnimator; private ValueAnimator secAnimator; private ValueAnimator thirdAnimator; private int mEndCirIRadius; private int mEndCirMRadius; private int mEndCirORadius; private ValueAnimator mEndAnimator; // 正在结束,只绘制结束动画 private boolean isMoveEnd = false; public SecondPellet(int x, int y) { super(x, y); } @Override protected void initConfig() { mEndMovingLength = -25; mPaint = new Paint(); mPaint.setStrokeJoin(Paint.Join.ROUND); mPaint.setStrokeCap(Paint.Cap.ROUND); mPaint.setAntiAlias(true); } @Override protected void initAnim() { //黄色圆出现->黄色圆变成圆边矩形 firAnimator = ValueAnimator.ofFloat(0, 1, 2).setDuration(600); firAnimator.setRepeatCount(0); firAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float factor = (float) animation.getAnimatedValue(); if (factor < 1) { mFirYellowCirRadius = 20 + (int) ((float) animation.getAnimatedValue() * (MAX_RADIUS_CIRCLE - 20)); mRedCirStrokeFactor = (int) (14 + (float) animation.getAnimatedValue() * 20); } else { mLineLeftOffset = (int) (MOVE_MAX_LINTH * (factor - 1)); } } }); firAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mFirYellowCirRadius = 0; mRedCirCleRadius = 60; mRedCirStrokeFactor = 50; mSecYellowCirRadius = 0; secAnimator.start(); } @Override public void onAnimationStart(Animator animation) { mIsCirLineShow = true; } }); // firAnimator.start(); secAnimator = ValueAnimator.ofFloat(0, 0.5f, 1, 1.25f, 1.5f, 1.75f, 2).setDuration(2400); secAnimator.setRepeatCount(0); secAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float factor = (float) animation.getAnimatedValue(); float changeValue = 0; if (factor <= 1.0f) { mLineRightOffset = (int) (MOVE_MAX_LINTH * factor); } else { changeValue = 2 - factor; //线变短变成圆一会消失,交给第三个小球处理 mIsCirLineShow = false; mAroundLineDegrees = (int) (90 * changeValue); if (factor < 1.5) { changeValue = (1.5f - factor) * 2; mAroundLineInsideP = MAX_RADIUS_CIRCLE - (int) (MAX_RADIUS_CIRCLE * changeValue); //红球缩小至20时就停止缩小 if (mRedCirCleRadius > 20) { mRedCirStrokeFactor = (int) (50 * changeValue); mRedCirCleRadius = MAX_RADIUS_CIRCLE - mAroundLineInsideP; } //中心小黄球出现 mFirYellowCirRadius = (int) (10 * (1 - changeValue)); } //底层黄球出现(环) if (factor > 1.5) { changeValue = (factor - 1.5f) * 2; mIsAroundPointV = true; mAroundPointY = (int) ((MAX_RADIUS_CIRCLE / 2) * changeValue); mSecYellowCirRadius = (int) (30 * changeValue); } } } }); secAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { thirdAnimator.start(); } }); //黄球(环)放大,再缩小,缩小过程伴随着环绕行星点变线向内伸长。 thirdAnimator = ValueAnimator.ofFloat(0, 5).setDuration(3000); thirdAnimator.setRepeatCount(0); thirdAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float factor = (float) animation.getAnimatedValue(); float changeValue = 0; if (factor < 1.0f) { //黄球放大 mSecYellowCirRadius = (int) (30 + 15 * (factor)); } else if (factor < 2.0f) { changeValue = 2 - factor; //黄球缩小 mSecYellowCirRadius = (int) (45 * changeValue); //点成线 mAroundLineInsideP = MAX_RADIUS_CIRCLE - (int) (MAX_RADIUS_CIRCLE / 3 * (1 - changeValue)); } else if (factor < 2.25f) { //停顿一下。 } else if (factor < 3.0f) { changeValue = (3.0f - factor) * 4 / 3; //线内聚 mIsAroundPointV = false; mAroundLineOutsideP = (int) (MAX_RADIUS_CIRCLE * changeValue); mAroundLineInsideP = (int) (MAX_RADIUS_CIRCLE / 3 * 2 * changeValue); //黄球缩小,红球放大 mFirYellowCirRadius = (int) (10 * changeValue); mRedCirStrokeFactor = 30;//(int) (16 + 10 * (1 - (3.0f - factor) * 4 / 3)); mRedCirCleRadius = (int) (20 + 15 * (1 - changeValue)); } else if (factor < 4.0f) { //停顿一下 } else if (factor < 5.0f) { changeValue = factor - 4.0f; //红球(环)内边外扩,内部黄球放大 mFirYellowCirRadius = (int) (20 * changeValue); mRedCirStrokeFactor = (int) (30 - 16 * changeValue); mRedCirCleRadius = (int) (35 + 8 * changeValue); } } }); thirdAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mAroundLineInsideP = MAX_RADIUS_CIRCLE; mAroundLineOutsideP = MAX_RADIUS_CIRCLE; mLineLeftOffset = 0; mLineRightOffset = 0; // firAnimator.start(); if (mAnimatorStateListen != null) { mAnimatorStateListen.onAnimatorEnd(); } } }); } @Override public void startAnim() { firAnimator.start(); } @Override protected void initEndAnim() { mEndAnimator = ValueAnimator.ofFloat(0, 1, 2).setDuration(mDuration); // mEndAnimator.setRepeatCount(2); mEndAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float zoroToOne = (float) animation.getAnimatedValue(); if (zoroToOne <= 1.0f) { mCurX = (int) (mPerX + zoroToOne * mEndMovingLength); mEndCirIRadius = (int) (MAX_RADIUS_CIRCLE * zoroToOne); if (zoroToOne <= 0.5f) { zoroToOne = 2 * zoroToOne; } else { zoroToOne = 1 - 2 * (zoroToOne - 0.5f); } mEndCirMRadius = (int) (MAX_RADIUS_CIRCLE * zoroToOne); } else { if (!isMoveEnd) { isMoveEnd = true; if (mAnimatorStateListen != null) { mAnimatorStateListen.onMoveEnd(); } } zoroToOne = 2 - zoroToOne; mEndCirIRadius = (int) (MAX_RADIUS_CIRCLE * zoroToOne); if (zoroToOne >= 0.5f) { zoroToOne = (1.0f - zoroToOne) * 2; } else { zoroToOne = zoroToOne * 2; } mEndCirORadius = (int) (MAX_RADIUS_CIRCLE * zoroToOne); } } }); } @Override public void drawSelf(Canvas canvas) { if (!isMoveEnd) { if (mPaint.getStyle() != Paint.Style.STROKE) { mPaint.setStyle(Paint.Style.STROKE); } mPaint.setColor(Config.YELLOW); mPaint.setStrokeWidth(mSecYellowCirRadius); canvas.drawCircle(getCurX(), getCurY(), mSecYellowCirRadius / 2, mPaint); mPaint.setColor(Config.RED); mPaint.setStrokeWidth(mRedCirStrokeFactor); canvas.drawCircle(getCurX(), getCurY(), mRedCirCleRadius - mRedCirStrokeFactor / 2, mPaint); mPaint.setColor(Config.YELLOW); mPaint.setStrokeWidth(mFirYellowCirRadius); canvas.drawCircle(getCurX(), getCurY(), mFirYellowCirRadius / 2, mPaint); //黄色圆移动,等同圆角的线 //TODO 结尾问题。 if (mIsCirLineShow) { mPaint.setStrokeWidth(mLineStrokeWidth); canvas.drawLine(getCurX() + mLineRightOffset, getCurY(), getCurX() + mLineLeftOffset, getCurY(), mPaint); } drawAroundLine(canvas); if (mIsAroundPointV == true) { drawAroundPoint(canvas); } } if (mIsEnd) { if (!mIsEndAnimStart) { mEndAnimator.start(); mIsEndAnimStart = true; } mPaint.setStyle(Paint.Style.FILL); mPaint.setColor(Config.GREEN); canvas.drawCircle(getCurX(), getCurY(), mEndCirIRadius, mPaint); mPaint.setColor(Config.YELLOW); canvas.drawCircle(getCurX(), getCurY(), mEndCirMRadius, mPaint); mPaint.setColor(Config.RED); canvas.drawCircle(getCurX(), getCurY(), mEndCirORadius, mPaint); mPaint.setStyle(Paint.Style.STROKE); return; } } private void drawAroundLine(Canvas canvas) { mPaint.setColor(Config.RED); mPaint.setStrokeWidth(LINE_STROKE_LENGTH); for (int i = 0; i < 8; i++) { canvas.save(); canvas.rotate(45 * i + mAroundLineDegrees, getCurX(), getCurY()); canvas.drawLine(getCurX(), getCurY() - mAroundLineOutsideP, getCurX(), getCurY() - mAroundLineInsideP, mPaint); canvas.restore(); } } private void drawAroundPoint(Canvas canvas) { mPaint.setStyle(Paint.Style.FILL); for (int i = 0; i < 8; i++) { mPaint.setAlpha(160); canvas.save(); canvas.rotate(45 * i + mAroundLineDegrees, getCurX(), getCurY()); canvas.drawCircle(getCurX(), getCurY() - MAX_RADIUS_CIRCLE / 2 - mAroundPointY, AROUND_POINT_RADIUS, mPaint); canvas.restore(); } } }