粒子效果的实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/mingyunxiaohai/article/details/88916761

效果图
在这里插入图片描述

想要实现一个图片的粒子效果,思路就是

  1. 遍历图片的宽高,通过Bitmap.getPixel(row,cloum)这个方法,返回值我们可以拿到当前像素点的颜色值,我们也能拿到当前的坐标点,然后封装成一个一个的小球对象,保存在集合里面。
  2. 在onDraw里面遍历集合根据这些小球的坐标点和颜色值绘制圆圈。如果我们取的像素足够密,绘制出来的原点可以组成这个图片。
  3. 动画效果,通过属性动画,在onAnimationUpdate方法中根据一定的算法不断更新小球对象的x,y坐标点。这个算法可以自己定,比如通过自有落体的公式,或者随机数等。
  4. 在onTouchEvent方法中监听ACTION_DOWN事件开启动画
  5. 如果直接取图片的所有像素,如果图片很大的话,会非常卡,如果不取全部的,那绘制出来效果没原图清晰,我们可以通过一个标志位,开始绘制原图,点击之后在绘制小圆球。

创建一个Ball对象,用来保存将要绘制的每个点的坐标和当坐标更新时的变化速度。

public class Ball {

    public int color;
    //x坐标
    public float x;
    //y坐标
    public float y;
    //半径
    public float r;

    //水平速度
    public float vX;
    //垂直速度
    public float vY;
    //水平加速度
    public float aX;
    //垂直加速度
    public float aY;

}

创建一个bitmap,遍历它的宽高,获取像素值,和坐标值,封装成一个一个的小球并保存起来。为了提高效率这里的遍历每次+2,可根据实际情况更改。

 mBitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.shader);
 for (int i = 0; i < mBitmap.getWidth()/d; i+=2) {
            for (int j = 0; j < mBitmap.getHeight()/d; j+=2) {
                Ball ball = new Ball();
                ball.color = mBitmap.getPixel(i,j);
                ball.x = i*d+d/2;
                ball.y = j*d+d/2;
                ball.r = d/2;

                //速度(-20,20)
                ball.vX = (float) (Math.pow(-1, Math.ceil(Math.random() * 100)) * 20 * Math.random());
                ball.vY = rangInt(-15, 35);
                //加速度
                ball.aX = 0;
                ball.aY = 0.98f;

                mBalls.add(ball);
            }
        }

开始绘制,判断是绘制原图还是绘制小圆圈。

    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.translate(getWidth()/2-mBitmap.getWidth()/2,getHeight()/2-mBitmap.getHeight()/2);
        if(isShowBitmap){
            canvas.drawBitmap(mBitmap,0,0,null);
        }else {
            for (Ball ball : mBalls) {
                mPaint.setColor(ball.color);
                canvas.drawCircle(ball.x,ball.y,ball.r,mPaint);
            }
        }
    }

使用属性动画,动态的更新每个小球的坐标值然后重新绘制。

    splitAnimator = ValueAnimator.ofFloat(0,1);
        splitAnimator.setRepeatCount(-1);
        splitAnimator.setDuration(2000);
        splitAnimator.setInterpolator(new LinearInterpolator());
        splitAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                updateBall();
                invalidate();
            }
        });
      private void updateBall() {
        for (Ball ball : mBalls) {
            ball.x += ball.vX;
            ball.y += ball.vY;

            ball.vX += ball.aX;
            ball.vY += ball.aY;
        }
    }

OK完成,源码地址点击这里

猜你喜欢

转载自blog.csdn.net/mingyunxiaohai/article/details/88916761