首页 > 学院 > 开发设计 > 正文

波浪图

2019-11-09 13:50:40
字体:
来源:转载
供稿:网友

前几天撸了个贝塞尔曲线,最近看到波浪图很敢兴趣,想着也是贝塞尔曲线。真实做的时候使用的不是贝塞尔但是也是数学公式。其实贝塞尔曲线一样能做出来。

注意看那个浅红色部分。特意使用颜色不一样的


WaveView,主要靠做bitmap然后通过正弦直接看代码

public class WaveView extends View { //*************属性开始**************// /** * 振幅比例 */ PRivate static final float DEFAULT_AMPLITUDE_RATIO = 0.05f; /** * 水位比例 */ private static final float DEFAULT_WATER_LEVEL_RATIO = 0.5f; /** * 波长比例 */ private static final float DEFAULT_WAVE_LENGTH_RATIO = 1.0f; /** * 偏移 */ private static final float DEFAULT_WAVE_SHIFT_RATIO = 0.0f; /** * 后面波浪的颜色 */ public static final int DEFAULT_BEHIND_WAVE_COLOR = Color.parseColor("#28FFFFFF"); /** * 前面波浪的颜色 */ public static final int DEFAULT_FRONT_WAVE_COLOR = Color.parseColor("#3CFFFFFF"); /** * 外观样式 */ public static final ShapeType DEFAULT_WAVE_SHAPE = ShapeType.CIRCLE; public enum ShapeType { CIRCLE, SQUARE } /** * 是否展示波浪动画 */ private boolean mShowWave; /** * 着色器 */ private BitmapShader mWaveShader; /** * shader矩阵 */ private Matrix mShaderMatrix; /** * view的画笔 */ private Paint mViewPaint; /** * 边界border的画笔 */ private Paint mBorderPaint; /** * 默认振幅 */ private float mDefaultAmplitude; /** * 默认水位 */ private float mDefaultWaterLevel; /** * 默认wave宽度 */ private float mDefaultWaveLength; /** * 默认波浪角频率 */ private double mDefaultAngularFrequency; /** * 默认振幅比例 */ private float mAmplitudeRatio = DEFAULT_AMPLITUDE_RATIO; /** * 波浪宽度 */ private float mWaveLengthRatio = DEFAULT_WAVE_LENGTH_RATIO; /** * 波浪水位 */ private float mWaterLevelRatio = DEFAULT_WATER_LEVEL_RATIO; /** * 位移 */ private float mWaveShiftRatio = DEFAULT_WAVE_SHIFT_RATIO; /** * 默认后面波浪颜色 */ private int mBehindWaveColor = DEFAULT_BEHIND_WAVE_COLOR; /** * 默认前面波浪颜色 */ private int mFrontWaveColor = DEFAULT_FRONT_WAVE_COLOR; /** * 默认着色外观 */ private ShapeType mShapeType = DEFAULT_WAVE_SHAPE; //*************属性结束**************// public WaveView(Context context) { super(context); init(); } public WaveView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public WaveView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } /** * 做一些初始化的操作 */ private void init() { mShaderMatrix = new Matrix(); mViewPaint = new Paint(); mViewPaint.setAntiAlias(true); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); createShader(); } /** * 绘制初始波形 */ private void createShader() { mDefaultAngularFrequency = 2.0f * Math.PI / DEFAULT_WAVE_LENGTH_RATIO / getWidth(); //默认振幅()= 控件的高度* 默认振幅比例 mDefaultAmplitude = getHeight() * DEFAULT_AMPLITUDE_RATIO; mDefaultWaterLevel = getHeight() * DEFAULT_WATER_LEVEL_RATIO; mDefaultWaveLength = getWidth(); //创建长宽恰等于WaveView的Bitmap 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); //把波浪画到bitmap上面 //画一个正弦曲线 // y=Asin(ωx+φ)+h final int endX = getWidth() + 1; final int endY = getHeight() + 1; float[] waveY = new float[endX]; //初始化后面波浪 wavePaint.setColor(mBehindWaveColor); for (int beginX = 0; beginX < endX; beginX++) { //波浪形的x double wx = beginX * mDefaultAngularFrequency; //开始y的值通过公式计算 float beginY = (float) (mDefaultWaterLevel + mDefaultAmplitude * Math.sin(wx)); canvas.drawLine(beginX, beginY, beginX, endY, wavePaint); waveY[beginX] = beginY; } //初始化前面波浪 前面波浪相对于后面波浪的偏移量 wavePaint.setColor(mFrontWaveColor); final int wave2Shift = (int) (mDefaultWaveLength / 4); for (int beginX = 0; beginX < endX; beginX++) { canvas.drawLine(beginX, waveY[(beginX + wave2Shift) % endX], beginX, endY, wavePaint); } //产生一个画有一个位图的渲染器 , // Shader.TileMode.REPEAT: 在x轴上面的平铺模式、REPEAT:横向和纵向的重复渲染器图片,平铺 //Shader.TileMode.CLAMP 渲染器超出原始边界范围,会复制范围内边缘染色 // 在x轴采用横向和纵向平铺。在y轴采用渲染器超出原始边界范围,会复制范围内边缘染色 mWaveShader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.CLAMP); mViewPaint.setShader(mWaveShader); } @Override protected void onDraw(Canvas canvas) { //如果当前未显示wave if (mShowWave && mWaveShader != null) { //还必须确定自定义控件的shader 不能为空 if (mViewPaint.getShader() == null) { mViewPaint.setShader(mWaveShader); } //先做缩放变换 mShaderMatrix.setScale( mWaveLengthRatio / DEFAULT_WAVE_LENGTH_RATIO,//x轴的缩放比例 mAmplitudeRatio / DEFAULT_AMPLITUDE_RATIO,//y轴的缩放该比例 0,//中心点x mDefaultWaterLevel);//中心点y //再做平移,这里注意下,是postTranslate ,不是setTranslate.是因为需要后乘 mShaderMatrix.postTranslate(mWaveShiftRatio * getWidth(),//在x轴移动的量 (DEFAULT_WATER_LEVEL_RATIO - mWaterLevelRatio) * getHeight()); //在y轴移动的量, //y轴上使用正数进行平移将向下移动图像,而使用负数将向上移动图像。 mWaveShader.setLocalMatrix(mShaderMatrix); //自定义控件的边框宽度 float borderWidth = mBorderPaint == null ? 0f : mBorderPaint.getStrokeWidth(); switch (mShapeType) { case CIRCLE: if (borderWidth > 0) { //如果边框的宽度大于0,则绘制出一个挨着自定义控件的圆形。 //该圆的中心肯定在自定义控件的中心。 canvas.drawCircle(getWidth() / 2f, getHeight() / 2f, (getWidth() - borderWidth) / 2f - 1f, mBorderPaint); } //绘制自定义控件 float radius = getWidth() / 2f - borderWidth; //波形图已经在mViewPaint 中的shader中了 canvas.drawCircle(getWidth() / 2f, getHeight() / 2f, radius, mViewPaint); break; case SQUARE: if (borderWidth > 0) { canvas.drawRect( borderWidth / 2f, borderWidth / 2f, getWidth() - borderWidth / 2f - 0.5f, getHeight() - borderWidth / 2f - 0.5f, mBorderPaint); } canvas.drawRect(borderWidth, borderWidth, getWidth() - borderWidth, getHeight() - borderWidth, mViewPaint); break; } } else { mViewPaint.setShader(null); } } //*********************get和set开始********************************// /** * 得到偏移比例 * * @return 获得偏移的比例 */ public float getWaveShiftRatio() { return mWaveShiftRatio; } /** * 设置波浪转换偏移比例 * * @param waveShiftRatio waveShiftRatio 必须是 0 ~ 1.0的值,默认是0 */ public void setWaveShiftRatio(float waveShiftRatio) { if (mWaveShiftRatio != waveShiftRatio) { mWaveShiftRatio = waveShiftRatio; invalidate(); } } /** * 得到 水位比例 * * @return */ public float getWaterLevelRatio() { return mWaterLevelRatio; } /** * 设置水位比例 * * @param waterLevelRatio 必须是 0 ~ 1. 默认0.5f */ public void setWaterLevelRatio(float waterLevelRatio) { if (mWaterLevelRatio != waterLevelRatio) { mWaterLevelRatio = waterLevelRatio; invalidate(); } } /** * 得到振幅比例 * * @return */ public float getAmplitudeRatio() { return mAmplitudeRatio; } /** * 设置振幅比例 * * @param amplitudeRatio 默认是 0.05. 不能大于1 */ public void setAmplitudeRatio(float amplitudeRatio) { if (mAmplitudeRatio != amplitudeRatio) { mAmplitudeRatio = amplitudeRatio; invalidate(); } } /** * 得到宽度 * * @return */ public float getWaveLengthRatio() { return mWaveLengthRatio; } /** * 设置横向波浪宽度的比例 * * @param waveLengthRatio 默认1 */ public void setWaveLengthRatio(float waveLengthRatio) { mWaveLengthRatio = waveLengthRatio; } public boolean isShowWave() { return mShowWave; } public void setShowWave(boolean showWave) { mShowWave = showWave; } /** * 设置 边框的宽度和颜色 * * @param width * @param color */ public void setBorder(int width, int color) { if (mBorderPaint == null) { mBorderPaint = new Paint(); mBorderPaint.setAntiAlias(true); mBorderPaint.setStyle(Paint.Style.STROKE); } mBorderPaint.setColor(color); mBorderPaint.setStrokeWidth(width); invalidate(); } /** * 设置 波浪的颜色 * * @param behindWaveColor 后面波浪的颜色 * @param frontWaveColor 前面波浪的颜色 */ public void setWaveColor(int behindWaveColor, int frontWaveColor) { mBehindWaveColor = behindWaveColor; mFrontWaveColor = frontWaveColor; if (getWidth() > 0 && getHeight() > 0) { // need to recreate shader when color changed mWaveShader = null; createShader(); invalidate(); } } /** * 设置外形 * * @param shapeType */ public void setShapeType(ShapeType shapeType) { mShapeType = shapeType; invalidate(); } //*********************get和set结束********************************//}

WaveAnimatorHelper类,这个还有问题。太晚了。。睡觉去

public class WaveAnimatorHelper { /** * 动画集合 */ private static AnimatorSet mAnimatorSet; private static List<Animator> animators; /** * 偏移量动画 */ private static ObjectAnimator waveShiftAnim; /** * 水位高度动画 */ private static ObjectAnimator waterLevelAnim; /** * 振幅角度动画 */ private static ObjectAnimator amplitudeAnim; private static ObjectAnimator objectAnimator; /** * 是否暂停 */ private static boolean isPause = false; public enum ANIMATORTYPE { PROPERTYVALUES, ANIMATORSET } /** * 工具类的构造方法通常私有化 */ private WaveAnimatorHelper(ANIMATORTYPE type, float waterLevelStart, float waterLevelEnd, float waveShiftStart, float waveShiftEnd, float amplitudeStart, float amplitudeEnd, WaveView mWaveView, int duration) { //改变偏移量 if (type == ANIMATORTYPE.PROPERTYVALUES) {// PropertyValuesHolder waterLevelAnim = PropertyValuesHolder.ofFloat("waterLevelRatio", 0.0f, 0.5f); PropertyValuesHolder waterLevelAnim = PropertyValuesHolder.ofFloat("waterLevelRatio", waterLevelStart, waterLevelEnd);// PropertyValuesHolder waveShiftAnim = PropertyValuesHolder.ofFloat("waveShiftRatio", 0f, 1f); PropertyValuesHolder waveShiftAnim = PropertyValuesHolder.ofFloat("waveShiftRatio", waveShiftStart, waveShiftEnd);// PropertyValuesHolder amplitudeAnim = PropertyValuesHolder.ofFloat("amplitudeRatio", 0.0001f, 0.08f); PropertyValuesHolder amplitudeAnim = PropertyValuesHolder.ofFloat("amplitudeRatio", amplitudeStart, amplitudeEnd); objectAnimator = ObjectAnimator.ofPropertyValuesHolder(mWaveView, waterLevelAnim, waveShiftAnim, amplitudeAnim); objectAnimator.setDuration(duration); objectAnimator.setRepeatMode(REVERSE); objectAnimator.setRepeatCount(INFINITE); objectAnimator.start(); } else { animators = new ArrayList<>(); waveShiftAnim = ObjectAnimator.ofFloat( mWaveView, "waveShiftRatio", waveShiftStart, waveShiftEnd); // 无限 循环 waveShiftAnim.setRepeatCount(ValueAnimator.INFINITE); waveShiftAnim.setDuration(duration); //匀速线性差值器 waveShiftAnim.setInterpolator(new LinearInterpolator()); animators.add(waveShiftAnim);// 改变水位比例 waterLevelAnim = ObjectAnimator.ofFloat( mWaveView, "waterLevelRatio", waterLevelStart, waterLevelEnd); waterLevelAnim.setDuration(duration * 3); waterLevelAnim.setRepeatCount(ValueAnimator.INFINITE); waterLevelAnim.setRepeatMode(ValueAnimator.REVERSE); //减速差值器 waterLevelAnim.setInterpolator(new DecelerateInterpolator()); animators.add(waterLevelAnim);// 改变振幅比例 amplitudeAnim = ObjectAnimator.ofFloat( mWaveView, "amplitudeRatio", amplitudeStart, amplitudeEnd); amplitudeAnim.setRepeatCount(ValueAnimator.INFINITE); amplitudeAnim.setRepeatMode(ValueAnimator.REVERSE); amplitudeAnim.setDuration(duration * 2); amplitudeAnim.setInterpolator(new LinearInterpolator()); animators.add(amplitudeAnim); mAnimatorSet = new AnimatorSet(); mAnimatorSet.playTogether(animators); if (mAnimatorSet != null) { mAnimatorSet.start(); } } } /** * 通过ObjectAnimator.ofPropertyValuesHolder方式启动动画。3个动画持续时间相同 * * @param waterLevelStart 水位开始位置 * @param waterLevelEnd 水位结束位置 * @param waveShiftStart 偏移开始位置 * @param waveShiftEnd 偏移结束位置 * @param amplitudeStart 振幅开始 * @param amplitudeEnd 振幅结束 * @param waveView 当前waveview * @param duration 持续时间 * @return */ public static WaveAnimatorHelper startAnimatorWithPropertyValuesHolder (float waterLevelStart, float waterLevelEnd, float waveShiftStart, float waveShiftEnd, float amplitudeStart, float amplitudeEnd, WaveView waveView, int duration) { return new WaveAnimatorHelper(ANIMATORTYPE.PROPERTYVALUES, waterLevelStart, waterLevelEnd, waveShiftStart, waveShiftEnd, amplitudeStart, amplitudeEnd, waveView, duration); } /** * 通过ObjectAnimator.ofPropertyValuesHolder方式启动动画。3个动画持续时间相同 * * @param waterLevelStart 水位开始位置 * @param waterLevelEnd 水位结束位置 * @param waveShiftStart 偏移开始位置 * @param waveShiftEnd 偏移结束位置 * @param amplitudeStart 振幅开始 * @param amplitudeEnd 振幅结束 * @param waveView 当前waveview * @param duration 持续时间 * @return */ public static WaveAnimatorHelper startAnimatorWithAnimatorSet (float waterLevelStart, float waterLevelEnd, float waveShiftStart, float waveShiftEnd, float amplitudeStart, float amplitudeEnd, WaveView waveView, int duration) { return new WaveAnimatorHelper(ANIMATORTYPE.ANIMATORSET, waterLevelStart, waterLevelEnd, waveShiftStart, waveShiftEnd, amplitudeStart, amplitudeEnd, waveView, duration); } /** * 暂停PropertyValuesHolder动画 */ @TargetApi(Build.VERSION_CODES.KITKAT) public static void stopAnimatorWithPropertyValuesHolder() { if (objectAnimator != null) { if (!isPause) { objectAnimator.pause(); isPause = true; } } } /** * 继续PropertyValuesHolder动画 */ @TargetApi(Build.VERSION_CODES.KITKAT) public static void resumePropertyValuesHolder() { if (objectAnimator != null) { if (isPause) { objectAnimator.resume(); isPause = false; return; } objectAnimator.resume(); } } public static void stopAnimationWithAnimatorSet(){ if(mAnimatorSet != null){ } }}

在activity中多了几行代码

waveView = (WaveView) findViewById(R.id.wave1); waveView.setShowWave(true); waveView.setWaveColor( Color.parseColor("#28f16d7a"), Color.parseColor("#3cf16d7a")); waveView.setShapeType(WaveView.ShapeType.SQUARE); WaveAnimatorHelper.startAnimatorWithAnimatorSet(0.0f, 0.4f, 0f, 1f, 0.0001f, 0.2f, waveView, 1000);

GitHub地址

CSDN地址


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表