视差动画

来源:互联网 发布:惠普笔记本散热软件 编辑:程序博客网 时间:2024/05/16 18:51

作者 | 红橙Darren

地址 | http://www.jianshu.com/p/923513a70d15

声明 | 本文是 红橙Darren 原创,已获授权发布,未经原作者允许请勿转载



效果


太多太多的评论我其实是不会回的,如果要说什么只能说抱歉。我承认很多视频链接没那么好找,但是你如果留意用心了,肯定能获取到以前所有的直播视频链接。


分析和实现

2.1 效果分析:

写了那么多次效果,这个实现起来应该是个小 case ,留意观察有三部分动画
  1. 旋转动画,六个小球在不断地旋转
  2. 位移动画,六个小球往中心点聚合
  3. 扩散动画,当小球移动的最中心就开始扩散

2.2 分步实现:

1. 旋转动画,六个小球在不断地旋转

/**
* 绘制小圆的旋转动画
*/

private class RotationState extends SplashState {
   private ValueAnimator mAnimator;

   public RotationState() {
       // 属性动画
       mAnimator = ValueAnimator.ofFloat(0, (float) Math.PI * 2);
       mAnimator.setDuration(ROTATION_ANIMATION_TIME);
       mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
           @Override
           public void onAnimationUpdate(ValueAnimator animation) {
               // 不断获取值 当前大圆旋转的角度
               mCurrentRotationAngle = (float) animation.getAnimatedValue();
               // 提醒View重新绘制
               invalidate();
           }
       });
       mAnimator.setRepeatCount(-1);
       mAnimator.setInterpolator(new LinearInterpolator());
       // 开始计算
       mAnimator.start();
   }

   @Override
   public void draw(Canvas canvas) {
       canvas.drawColor(mSplashColor);
       // 绘制六个小圆 坐标
       float preAngle = (float) (2 * Math.PI / mCircleColors.length);
       for (int i = 0; i < mCircleColors.length; i++) {
           mPaint.setColor(mCircleColors[i]);
           // 初始角度 + 当前旋转的角度
           double angle = i * preAngle + mCurrentRotationAngle;
           float cx = (float) (mCenterX + mRotationRadius * Math.cos(angle));
           float cy = (float) (mCenterY + mRotationRadius * Math.sin(angle));
           canvas.drawCircle(cx, cy, mCircleRadius, mPaint);
       }
   }

   public void cancelAnimator() {
       mAnimator.cancel();
       mAnimator = null;
   }
}

2. 位移动画,六个小球往中心点靠拢

/**
* 绘制小圆的聚合动画
*/

private class MergeState extends SplashState {
   private ValueAnimator mAnimator;

   public MergeState() {
       // 属性动画
       mAnimator = ValueAnimator.ofFloat(mRotationRadius, 0);
       mAnimator.setDuration(SPLASH_ANIMATION_TIME / 2);
       mAnimator.setInterpolator(new AnticipateInterpolator(6f));
       mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
           @Override
           public void onAnimationUpdate(ValueAnimator animation) {
               // 不断获取值 当前大圆旋转的角度
               mCurrentRotationRadius = (float) animation.getAnimatedValue();
               // 提醒View重新绘制
               invalidate();
           }
       });

       mAnimator.addListener(new AnimatorListenerAdapter() {
           @Override
           public void onAnimationEnd(Animator animation) {
               mSplashState = new ExpandingState();
           }
       });

       // 开始计算
       mAnimator.start();
   }

   @Override
   public void draw(Canvas canvas) {
       canvas.drawColor(mSplashColor);
       // 绘制六个小圆 坐标
       float preAngle = (float) (2 * Math.PI / mCircleColors.length);
       for (int i = 0; i < mCircleColors.length; i++) {
           mPaint.setColor(mCircleColors[i]);
           // 初始角度 + 当前旋转的角度
           double angle = i * preAngle + mCurrentRotationAngle;
           float cx = (float) (mCenterX + mCurrentRotationRadius * Math.cos(angle));
           float cy = (float) (mCenterY + mCurrentRotationRadius * Math.sin(angle));
           canvas.drawCircle(cx, cy, mCircleRadius, mPaint);
       }
   }
}

3. 扩散动画,当小球移动的最中心就开始扩散

/**
* 绘制小圆的扩散动画
*/

private class ExpandingState extends SplashState {
   private ValueAnimator mAnimator;

   public ExpandingState() {
       // 属性动画
       mAnimator = ValueAnimator.ofFloat(0, mDiagonalDist);
       mAnimator.setDuration(SPLASH_ANIMATION_TIME/2);
       mAnimator.setInterpolator(new AccelerateInterpolator());
       mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
           @Override
           public void onAnimationUpdate(ValueAnimator animation) {
               // 不断获取值 当前大圆旋转的角度
               mHoleRadius = (float) animation.getAnimatedValue();
               // 提醒View重新绘制
               invalidate();
           }
       });
       // 开始计算
       mAnimator.start();
   }

   @Override
   public void draw(Canvas canvas) {
       if (mHoleRadius > 0) {
           float strokeWidth = mDiagonalDist - mHoleRadius;
           mPaintBackground.setStrokeWidth(strokeWidth);
           float radius = mHoleRadius + strokeWidth / 2;
           canvas.drawCircle(mCenterX, mCenterY, radius, mPaintBackground);
       } else {
           canvas.drawColor(mSplashColor);
       }
   }
}

这期是自定义 View 部分的最后一次写效果了,写得也比较简单,因为毕竟前面写过那么多次,关于画笔绘制和属性动画我就不再详讲了。



与之相关

1 30 岁程序员的选择,一线 OR 二线?

2 Android 面试 | 全站式导航



微信号:code-xiaosheng





公众号

「code小生」


原创粉丝点击