天天看點

炫酷動畫效果

先上下最終實作的效果圖:

炫酷動畫效果

制作的gif效果有點閃哈,真機上效果要好一點的 接下來進入正題:

1.繪制波浪

主要利用斐波那契函數繪制二條曲線,然後不停地偏移一些距離實作波浪移動的效果 以下代碼是直接使用某位大神的代碼進行的修改

protected void onDraw(Canvas canvas) {
        canvas.setDrawFilter(mDrawFilter);
        mAbovePath.reset();
        mBelowWavePath.reset();
        φ -= 0.1f;
        float y, y2;
        ω = 2 * Math.PI / getWidth();
        mAbovePath.moveTo(getLeft(), getBottom());
        mBelowWavePath.moveTo(getLeft(), getBottom());
        for (float x = 0; x <= getWidth(); x += 20) {
            /**
             *  y=Asin(ωx+φ)+k
             *  A—振幅越大,波形在y軸上最大與最小值的內插補點越大
             *  ω—角速度, 控制正弦周期(機關角度内震動的次數)
             *  φ—初相,反映在坐标系上則為圖像的左右移動。這裡通過不斷改變φ,達到波浪移動效果
             *  k—偏距,反映在坐标系上則為圖像的上移或下移。
             */
            y = (float) (height / 8 * Math.cos(ω * x + φ) + height / 8 * 3 + height / 2);
            y2 = (float) (height / 8 * Math.sin(ω * x + φ) + height / 2);
            mAbovePath.lineTo(x, y);
            mBelowWavePath.lineTo(x, y2);
            //回調 把y坐标的值傳出去(在activity裡面接收讓小機器人随波浪一起搖擺)
            mWaveAnimationListener.OnWaveAnimation(y);
        }
        for(int i=0;i<boards.size();i++){
            boards.get(i).drawBoard(canvas);
        }
        mAbovePath.lineTo(getRight(), getBottom());
        mBelowWavePath.lineTo(getRight(), getBottom());
        canvas.drawPath(mAbovePath, mAboveWavePaint);
        canvas.drawPath(mBelowWavePath, mBelowWavePaint);
        postInvalidateDelayed(20);
    }
           

2.繪制小船

建立一個小船類,根據x,y坐标在上面繪制一個bitmap,然後每次随機的向左偏移一段距離,實作移動。

public class Board {
    int width;Context context;int type;
    int left;
    public Board(int width,Context context, int type) {
        this.width = width;
        this.left=(int)(r.nextInt(100)*width/100);
        this.context = context;
        this.type = type;
    }
    Random r=new Random();
    public void drawBoard(Canvas canvas) {
        Paint paint = new Paint();
        int resource=R.mipmap.board1;
        switch (type){
            case 0:
                resource=R.mipmap.board1;
                break;
            case 1:
                resource=R.mipmap.board2;
                break;
            case 2:
                resource=R.mipmap.board3;
                break;
            case 3:
                resource=R.mipmap.board4;
                break;
            case 4:
                resource=R.mipmap.board5;
                break;
            case 5:
                resource=R.mipmap.board6;
                break;
        }
        Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resource);
        canvas.drawBitmap(bitmap, left, WaveView.getHeight(left)-bitmap.getHeight()/6*5, paint);
        left-=r.nextInt(3)*width/1000;
        if(left<=-bitmap.getWidth()){
            left=width;
        }
    }
}
           

在WaveView中提供根據X坐标擷取Y坐标的方法

public static float getHeight(int left) {
        return (float) (height / 8 * Math.cos(ω * left + φ) + height / 8 * 3 + height / 2);
    }
           

最後再WaveView的OnDraw方法中同時繪制所有的小船

for(int i=0;i<boards.size();i++){
            boards.get(i).drawBoard(canvas);
        }
           

3.繪制小魚

小魚繪制比較複雜,是直接照搬國外大牛做的,我稍微修改了下,給魚随機産生顔色和移動速度

fishDrawable = new FishDrawable(context, random.nextInt(255), random.nextInt(255), random.nextInt(255));
           

然後在布局中添加10條

RelativeLayout fishpool= (RelativeLayout) findViewById(R.id.fishpool);
        int i=0;
        do{
            fishpool.addView(new FishDrawableView(this));
            i++;
        }while (i<10);
           

到此,就完工了!

感興趣的可以在下方連結進行下載下傳,感覺還可以,幫忙給個star吧!

Github傳送門