欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

贝塞尔曲线绘制波浪

程序员文章站 2023-12-27 09:10:09
...

效果图:
贝塞尔曲线绘制波浪

关于贝塞尔曲线的介绍可以参照文章

https://www.cnblogs.com/wjtaigwh/p/6647114.html

了解完贝塞尔曲线就来完成波浪自定义View

大体思路就是先绘制一条超出屏幕长的二阶贝塞尔曲线,然后再动画循环平移曲线。

package com.xingyun.waveapplication;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;

/**
 * Created by SY on 2018/5/1.
 */

public class WaveView1 extends View {
private int width = 0;
private int height = 0;
private int baseHeight = 0;// 波浪高度
private int waveHeight = 200;// 波峰波、波谷高度
private int waveWidth;//波浪宽度
private float offset = 0;//偏移量
private Paint paint;


public WaveView1(Context context, AttributeSet attrs) {
    super(context, attrs);
    initPaint();
}

/**
 * 设置开启动画
 */
private void startAni() {
    ValueAnimator animator = ValueAnimator.ofFloat(0, waveWidth);
    animator.setInterpolator(new LinearInterpolator());
    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            float animatorValue = (float) animation.getAnimatedValue();
            offset = animatorValue;
            postInvalidate();
        }
    });
    animator.setDuration(1000);
    animator.setRepeatCount(ValueAnimator.INFINITE);
    animator.start();
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawPath(getPath(), paint);
}

//初始化paint
private void initPaint() {
    paint = new Paint();
    paint.setColor(Color.parseColor("#88FFFFFF"));
    paint.setStyle(Paint.Style.FILL);
}

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);
    width = getMeasuredWidth();
    height = getMeasuredHeight();
    waveWidth = width;
    baseHeight = height / 2;
    startAni();
}


/**
 * 生成path
 *
 * @return
 */
private Path getPath() {
    int itemWidth = waveWidth / 2;//波长
    Path path = new Path();
    path.moveTo(-itemWidth * 3 , baseHeight);//起始点坐标
    for (int count = -3; count < 2; count++) {
        int controlX = count * itemWidth;
        path.quadTo(controlX + itemWidth / 2 + offset,//控制点的X
                getWaveHeight(count),//控制点的Y
                controlX + itemWidth + offset,//结束点的X
                baseHeight//结束点的Y
        );
    }
    //封闭区域
    path.lineTo(width, height);
    path.lineTo(0, height);
    path.close();
    return path;
}

//计算波峰、波谷
private int getWaveHeight(int num) {
    if (num % 2 == 0) {
        return baseHeight - waveHeight;
    }
    return baseHeight + waveHeight;
}

}

贝塞尔曲线绘制波浪

初始化画笔之后再onLayout方法获取宽高,然后ondraw方法里绘制关键的曲线。通过getPath方法得到曲线的path。通过path.moveTo方法设置起始点坐标,调用path.quadTo绘制曲线,quadTo四个参数分别为控制点的XY坐标和结束点的XY坐标。完成后调用path.lineTo连接屏幕底部,将区域封闭起来。其中控制点Y坐标为一上一下交替,通过 getWaveHeight方法判断是波峰还是波谷。这样波浪曲线就绘制完成了。最后只要设置动画不断重绘并且循环动画就完成了。

上一篇:

下一篇: