根据正弦:y=Asin(ωx+φ)+h 画出静态的曲线。
再通过改变相位:ωx+φ,来实现动画。
![](https://img.haomeiwen.com/i26463879/789307044b1072d5.png)
/**
* @ClassName WaveView
* @Description TODO
* @Author shufeng.jiang
* @Date 2022/4/20 14:06
*/
public class WaveView extends View {
/**
* y=Asin(ωx+φ)+h 周期:T=2π/ω
*/
/* 画笔 */
Paint paint1 = new Paint();
public WaveView(Context context) {
super(context);
}
public WaveView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initPaint();
}
public WaveView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initPaint();
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public WaveView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
}
/* 控件宽 */
float xAxis=0;
/* 控件高 */
float yAxis=0;
/* 正弦函数的周期 */
float mCycle=0;
/* 曲线下移的距离 */
float wavelevel=0;
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
xAxis = getWidth(); // 控件的宽
yAxis = getHeight() ; // 控件的高
wavelevel = yAxis/2; // wavelevel 为 y=Asin(ωx+φ)+h 的 h
mCycle = (float) (2 * Math.PI / xAxis/1.5); // 根据宽度计算三角函数周期
waveAnim();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.WHITE);
createShader(canvas);
}
float startXAxis=0;
private void createShader(Canvas canvas){
for(int i=0;i<xAxis;i++){
float startYAxis = (float) (100*Math.sin(mCycle*i+startXAxis)+wavelevel);
float endYAxis = (float) (100*Math.sin(mCycle*(i+1)+startXAxis)+wavelevel);
// canvas.drawLine(i, startYAxis, i+1, endYAxis , paint1); // 这样是绘制正弦曲线
canvas.drawLine(i, startYAxis, i+1, yAxis, paint1); // 这样将绘制正弦曲线以下的部分。
}
}
private void initPaint(){
paint1.setColor(Color.BLUE); // 设置画笔颜色
paint1.setStrokeWidth(4.0f); // 设置画笔宽度
paint1.setAntiAlias(true); // 是否抗锯齿
/** Paint.Style.STROKE 只绘制图形轮廓(描边)
*Paint.Style.FILL 只绘制图形内容
*Paint.Style.FILL_AND_STROKE 既绘制轮廓也绘制内容
*/
paint1.setStyle(Paint.Style.STROKE);
}
public void waveAnim() {
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0F, 1.0f);
valueAnimator.setDuration(110000);
valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Float aFloat = Float.valueOf(animation.getAnimatedValue().toString());
//核心代码,重要的是在动画的过程中改变正弦波的相位,从 0 到 控件宽 无限变化就可以实现正弦波的移动
startXAxis = getWidth() * aFloat;
invalidate();
}
});
valueAnimator.start();
}
}
到次绘制完成!
第一次自定义View,各位大佬勿喷。目前写简书的意义就是做笔记,方便自己后期借鉴。
网友评论