视差动画 - 雅虎新闻摘要加载
效果
太多太多的评论我其实是不会回的,如果要说什么只能说抱歉。我承认很多视频链接没那么好找,但是你如果留意用心了,肯定能获取到以前所有的直播视频链接。
分析和实现
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 部分的最后一次写效果了,写得也比较简单,因为毕竟前面写过那么多次,关于画笔绘制和属性动画我就不再详讲了。
与之相关
日
更
精
彩
微信号:code-xiaosheng
公众号
「code小生」