美文网首页自定义控件
[Android高级动画] 如何让点扩散再聚合?

[Android高级动画] 如何让点扩散再聚合?

作者: 小米Metre | 来源:发表于2019-06-09 19:28 被阅读23次
    如何让多个点扩散再聚合?

    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);
            }
        }
    }
    
    

    相关文章

      网友评论

        本文标题:[Android高级动画] 如何让点扩散再聚合?

        本文链接:https://www.haomeiwen.com/subject/fegnxctx.html