Android水纹波浪动画

先上效果图

这里写图片描述

实现原理

这里写图片描述

整体思路以下:
一、将波浪效果绘制成一个静态的图片
二、将图片往水平和竖直方向,同时并按必定的速率移动java

在实现的过程当中,主要利用正弦函数 y=Asin(ωx+φ)+h ,设置四个参数(振幅、高度、波长和偏移)来实现波浪的动画效果。web

Wate Level(水位):波浪静止时水面距离底部的高度
Amplitude(振幅):波浪垂直振动时偏离水面的最大距离
Wave Length(波长):一个完整的波浪的水平长度
Wave Shift(偏移):波浪相对于初始位置的水平偏移canvas

代码模块

1、绘制波浪图片ide

mDefaultWaterLevel = getHeight() * DEFAULT_WATER_LEVEL_RATIO;
        float mDefaultWaveLength = getWidth();
        float mDefaultAmplitude = getHeight() * DEFAULT_AMPLITUDE_RATIO;
        double mDefaultAngularFrequency = 2.0f * Math.PI / DEFAULT_WAVE_LENGTH_RATIO / getWidth();

        Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);

        Paint wavePaint = new Paint();
        wavePaint.setStrokeWidth(2);
        wavePaint.setAntiAlias(true);

            // y=Asin(ωx+φ)+h 正弦曲线
        final int endX = getWidth() + 1;
        final int endY = getHeight() + 1;

        float[] waveY = new float[endX];

        wavePaint.setColor(Color.parseColor("#71CFFF")); //后面的波浪
        for (int beginX = 0; beginX < endX; beginX++) {
            double wx = beginX * mDefaultAngularFrequency;
            float beginY = (float) (mDefaultWaterLevel + mDefaultAmplitude * Math.sin(wx));
            canvas.drawLine(beginX, beginY, beginX, endY, wavePaint);

            waveY[beginX] = beginY;
        }

        wavePaint.setColor(Color.parseColor("#37BFFF")); //前面的波浪
        final int wave2Shift = (int) (mDefaultWaveLength / 4);
        for (int beginX = 0; beginX < endX; beginX++) {
            canvas.drawLine(beginX, waveY[(beginX + wave2Shift) % endX], beginX, endY, wavePaint);
        }

        //将波浪曲线的Bitmap变量赋值给画笔
        mWaveShader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
        mViewPaint.setShader(mWaveShader);

2、重写onDrawsvg

@Override
    protected void onDraw(Canvas canvas) {
        if (mWaveShader != null) {
            if (mViewPaint.getShader() == null) {
                mViewPaint.setShader(mWaveShader);
            }

            //根据水位的高度定义 mShaderMatrix 的规模
            mShaderMatrix.setScale(1, 1, 0, mDefaultWaterLevel);

            //根据水位的高度和偏移定义 mShaderMatrix 在起始时的位置
            mShaderMatrix.postTranslate(mWaveShiftRatio * getWidth(), (DEFAULT_WATER_LEVEL_RATIO - mWaterLevelRatio) * getHeight());

            //将 mShaderMatrix 设置给波浪
            mWaveShader.setLocalMatrix(mShaderMatrix);

            canvas.drawRect(0, 0, getWidth(), getHeight(), mViewPaint);
        } else {
            mViewPaint.setShader(null);
        }
    }

3、定义横纵的动画序列函数

List<Animator> mAnimators = new ArrayList<Animator>();
        ObjectAnimator waveShiftAnim = ObjectAnimator.ofFloat(mWaveView, "waveShiftRatio", 0f, 1f); //水平方向循环
        waveShiftAnim.setRepeatCount(ValueAnimator.INFINITE);
        waveShiftAnim.setDuration(2000);
        waveShiftAnim.setInterpolator(new LinearInterpolator());
        mAnimators.add(waveShiftAnim);

        ObjectAnimator waterLevelAnim = ObjectAnimator.ofFloat(mWaveView, "waterLevelRatio", mCurrentHeight, height); //竖直方向从0%到x%
        waterLevelAnim.setDuration(6000);
        waterLevelAnim.setInterpolator(new DecelerateInterpolator());
        mAnimators.add(waterLevelAnim);

        mWaveView.invalidate(); //刷新动画
        AnimatorSet mAnimatorSet = new AnimatorSet();
        mAnimatorSet.playTogether(mAnimators);
        mAnimatorSet.start();

开源分享

源代码工程:http://download.csdn.net/detail/chuck_0430/9738349post

转载请注明出处,谢谢!动画

另声明:本人参考http://www.jianshu.com/p/e711e22e053e的实现效果,完成了本身的需求。特此感谢!spa