如何让多个点扩散再聚合?
like this:
效果图一、如何绘制多个点为一个圆形
该篇主要讲,如何让点扩散再聚合
二、如何让多个点扩散再聚合呢?
1、原理分析:
该效果可分为两步:先将点扩散、再将点聚合在一起。
扩散:可以通过放大,点围成的圆的半径。
聚合:也是一样的,就是缩小点围成的圆的半径。
这里会使用到OvershootInterpolator插值器。该插值器,到一定值后,又会再回到原来位置。刚好可以实现聚合的效果。
2、具体实现:
定义属性动画
//mCircleRadius小球的半径
//mRadius小球围成的圆的半径
ValueAnimator mAnimator = ValueAnimator.ofFloat(mCircleRadius,mRadius);
mAnimator.setDuration(1000);
//OvershootInterpolator 向前甩一定值后再回到原来位置
// (tension=20,影响扩大比例的值)
mAnimator.setInterpolator(new OvershootInterpolator(20f));
//mAnimator.setRepeatCount(2);//默认0,执行一次
mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//扩散圆的半径的变化值
mCurrentRadius = (float)animation.getAnimatedValue();
invalidate();
}
});
//reverse()动画反向执行
mAnimator.reverse();
绘制小球:
private void drawBallState(Canvas canvas){
double degrees = Math.PI * 2 / colors.length;
for (int i = 0; i < colors.length; i++) {
// x = r * cos(a) + centX;
// y= r * sin(a) + centY;
mPaint.setColor(colors[i]);
float angle = (float) ((i * degrees) + mCurrentRotateDegrees);
float cx = (float) (mCurrentRadius * Math.cos(angle) + mCenterX);
float cy = (float) (mCurrentRadius * Math.sin(angle) + mCenterY);
canvas.drawCircle(cx,cy,mCircleRadius,mPaint);
}
}
以上就可以是实现,扩散再聚合效果啦!
最后附上完整代码:
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.view.animation.OvershootInterpolator;
import androidx.annotation.Nullable;
public class CircleView extends View {
public CircleView(Context context) {
this(context,null);
}
public CircleView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public CircleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private Paint mPaint = new Paint();
private int[] colors;
//旋转圆的中心坐标
private float mCenterX;
private float mCenterY;
//小球的半径
private float mCircleRadius = 20;
//小球围成的圆的半径
private float mRadius = 100;
private float mCurrentRotateDegrees;
private float mCurrentRadius = mRadius;
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mCenterX = w * 1f /2;
mCenterY = h * 1f/2;
}
private void init(){
mPaint.setStyle(Paint.Style.FILL);
colors = getResources().getIntArray(R.array.color_array);
}
private BallState mBallState;
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(mBallState == null){
mBallState = new RotateState();
}
mBallState.drawState(canvas);
}
class RotateState implements BallState{
private RotateState(){
ValueAnimator mAnimator = ValueAnimator.ofFloat(0,(float) Math.PI);
mAnimator.setDuration(1000);
//LinearInterpolator以常量速率改变
mAnimator.setInterpolator(new LinearInterpolator());
mAnimator.setRepeatCount(2);
mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mCurrentRotateDegrees = (float)animation.getAnimatedValue();
invalidate();
}
});
mAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
//旋转动画结束后,开始扩散聚合动画
mBallState = new MergeState();
}
});
mAnimator.start();
}
@Override
public void drawState(Canvas canvas) {
drawBallState(canvas);
}
}
class MergeState implements BallState{
private MergeState(){
ValueAnimator mAnimator = ValueAnimator.ofFloat(mCircleRadius,mRadius);
mAnimator.setDuration(1000);
//OvershootInterpolator 向前甩一定值后再回到原来位置 (tension影响扩大比例的值)
mAnimator.setInterpolator(new OvershootInterpolator(20f));
//mAnimator.setRepeatCount(2);//默认0,执行一次
mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mCurrentRadius = (float)animation.getAnimatedValue();
Log.d("CircleView","onAnimationUpdate | mCurrentRadius-->"+mCurrentRadius);
invalidate();
}
});
//mAnimator.start();
//动画反向执行
mAnimator.reverse();
}
@Override
public void drawState(Canvas canvas) {
drawBallState(canvas);
}
}
interface BallState{
void drawState(Canvas canvas);
}
private void drawBallState(Canvas canvas){
double degrees = Math.PI * 2 / colors.length;
for (int i = 0; i < colors.length; i++) {
// x = r * cos(a) + centX;
// y= r * sin(a) + centY;
mPaint.setColor(colors[i]);
float angle = (float) ((i * degrees) + mCurrentRotateDegrees);
float cx = (float) (mCurrentRadius * Math.cos(angle) + mCenterX);
float cy = (float) (mCurrentRadius * Math.sin(angle) + mCenterY);
canvas.drawCircle(cx,cy,mCircleRadius,mPaint);
}
}
}
网友评论