先上效果图
实现原理
总体思路如下:
1、将波浪效果绘制成一个静态的图片
2、将图片往水平和竖直方向,同时并按一定的速率移动
在实现的过程中,主要利用正弦函数 y=Asin(ωx+φ)+h ,设置四个参数(振幅、高度、波长和偏移)来实现波浪的动画效果。
Wate Level(水位):波浪静止时水面距离底部的高度
Amplitude(振幅):波浪垂直振动时偏离水面的最大距离
Wave Length(波长):一个完整的波浪的水平长度
Wave Shift(偏移):波浪相对于初始位置的水平偏移
代码模块
一、绘制波浪图片
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);
二、重写onDraw
@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);
}
}
三、定义横纵的动画序列
List mAnimators = new ArrayList();
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();
开源分享
转载请注明出处,谢谢!