貝塞爾曲線繪製波浪

效果圖:
這裏寫圖片描述

關於貝塞爾曲線的介紹可以參照文章

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方法判斷是波峯還是波谷。這樣波浪曲線就繪製完成了。最後只要設置動畫不斷重繪並且循環動畫就完成了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章