前言:贝塞尔曲线分为一级曲线,二级曲线,三级曲线和多级曲线,利用贝塞尔曲线可以做出很多有意思的动画和图形,今天我们就来实现一个比较简单的波浪线。
-----------------分割线---------------
初步认识贝塞尔曲线:
mPath.moveTo:设置起点。
mPath.rQuadTo:绘制曲线。
注意:第二个mPath.rQuadTo相对于自己的起始点--也即是上一个曲线的终点。
mPath.lineTo:闭合。
我们也可以使用path.quadTo(x1, y1, x2, y2)绘制二级贝塞尔曲线。
ok看完整代码:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.view.View;
/**
* Created by Fly on 2017/6/14.
*/
public class MyView extends View {
Paint mPaint;
Path mPath;
public MyView(Context context) {
super(context);
mPaint = new Paint();
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(10);
mPath = new Path();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPath.moveTo(100, 400);
mPath.rQuadTo(100, -150, 200, 0);
mPath.rQuadTo(100, 150, 200, 0);
mPath.lineTo(100, 400);
canvas.drawPath(mPath, mPaint);
}
}效果图:
---------------分割线---------------
如果想画动态的波浪线,需要我们不断的改变起点,废话不说直接看代码:
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;
import java.util.Random;
/**
* Created by Fly on 2017/6/13.
*/
public class WaveView2 extends View {
private Paint mPaint;
private Path mPath;
private int mWaveLength = 100;
private int dx;
private int dy;
public WaveView2(Context context) {
super(context);
init();
}
public WaveView2(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mPaint = new Paint();
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(10);
mPath = new Path();
}
int s = 50;
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPath.reset();
int originY = 300;
int mWaveHalfLength = mWaveLength / 2;
mPath.moveTo(-mWaveLength + dx, originY);
int max = 60;
int min = 40;
int maxW = 120;
int minW = 80;
Random random = new Random();
try {
Thread.sleep(500);
s = random.nextInt(max) % (max - min + 1) + min;
mWaveLength = random.nextInt(maxW) % (maxW - minW + 1) + minW;
} catch (InterruptedException e) {
e.printStackTrace();
}
//屏幕的宽度里面放多少个波长
for (int i = -mWaveLength; i < getWidth() + mWaveLength; i += mWaveLength) {
//相对绘制二阶贝塞尔曲线(相对于自己的起始点--也即是上一个曲线的终点 的距离dx1)
mPath.rQuadTo(mWaveHalfLength / 2, -s, mWaveHalfLength, 0);
mPath.rQuadTo(mWaveHalfLength / 2, s, mWaveHalfLength, 0);
//path.quadTo(x1, y1, x2, y2)
}
//颜色填充
//画一个封闭的空间
// mPath.lineTo(getWidth(), getHeight());
// mPath.lineTo(0, getHeight());
// mPath.close();
canvas.drawPath(mPath, mPaint);
}
public void startAnimation() {
ValueAnimator animator = ValueAnimator.ofInt(0, mWaveLength);
animator.setDuration(1000);
animator.setInterpolator(new LinearInterpolator());
//无限循环
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
dx = (int) animation.getAnimatedValue();
postInvalidate();
}
});
animator.start();
}
}然后在MainActivity中开启动画:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WaveView2 waveView = (WaveView2) findViewById(R.id.wv);
waveView.startAnimation();
}
}布局:
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
android:id="@+id/wv"
android:layout_width="match_parent"
android:layout_height="match_parent" />
效果:---------------------完-----------------