canvas 理解 辅助坐标系,辅助绘制
1
//剪切canvas,canvas本身位置不变,剩下的是截切内的区域,Rect是相对与整个屏幕的,而canvas是他剩余的不分并且位置不变(不回到左上角0点位置)
canvas.clipRect(new Rect(300, 300, 600, 600));
//canvas平移
canvas.translate(-400,-400);
//剪切canvas,在canvas上面剪切的剩余不分和Rect取交集
canvas.clipRect(new Rect(0, 0, 700, 700));
2
canvas.save();//将当前的画布状态压入栈,会面可以取出这个栈来canvas
canvas.restore();//弹出一个画布栈返回上一个栈的canvas状态,来canvas
canvas的两种操作
1,canvas位置(大小、位置)、matrix操作(translate scale rotate skew) 剪切操作clipX
2,canvas绘制 drawX
canvas.save()、canvas.saveLayer(),可以设置matrix操作(MATRIX_SAVE_FLAG )或者剪切操作(CLIP_SAVE_FLAG) 的状态来确定canvas.restore()恢复的是那种canvas.
MATRIX_SAVE_FLAG 操作translate scale rotate skew
测试代码
public static class SampleView extends View {
private Paint mPaint;
private Path mPath = new Path();
private float mPreX,mPreY;
private int mItemWaveLength = 800;
private int dx;
public SampleView(Context context) {
super(context);
init();
}
public SampleView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public SampleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public SampleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
public void init(){
setFocusable(true);
mPaint = new Paint();
mPaint.setAntiAlias(true);
startAnim();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//普通手势
// switch (event.getAction()){
// case MotionEvent.ACTION_DOWN: {
// mPath.moveTo(event.getX(), event.getY());
// return true;
// }
// case MotionEvent.ACTION_MOVE:
// mPath.lineTo(event.getX(), event.getY());
// postInvalidate();
// break;
// default:
// break;
// }
//贝塞尔手势
// switch (event.getAction()){
// case MotionEvent.ACTION_DOWN:{
// mPath.moveTo(event.getX(),event.getY());
// mPreX = event.getX();
// mPreY = event.getY();
// return true;
// }
// case MotionEvent.ACTION_MOVE:{
// float endX = (mPreX+event.getX())/2;
// float endY = (mPreY+event.getY())/2;
// mPath.quadTo(mPreX,mPreY,endX,endY);
// mPreX = event.getX();
// mPreY =event.getY();
// invalidate();
// }
// break;
// default:
// break;
// }
return super.onTouchEvent(event);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
wave(canvas);
// bsrDraw(canvas);
// bsrTest(canvas);
// test2(canvas);
// test1(canvas);
// canvas.drawColor(Color.WHITE);
// canvas.translate(10, 10);
// mPaint.setColor(Color.RED);
// canvas.drawCircle(75, 75, 75, mPaint);
// canvas.saveLayerAlpha(0, 0, 200, 200, 0x88, LAYER_FLAGS);
// mPaint.setColor(Color.BLUE);
// canvas.drawCircle(125, 125, 75, mPaint);
// canvas.restore();
}
public void startAnim(){
ValueAnimator animator = ValueAnimator.ofInt(0,mItemWaveLength);
animator.setDuration(2000);
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.setInterpolator(new LinearInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
dx = (int)animation.getAnimatedValue();
postInvalidate();
}
});
animator.start();
}
private void wave(Canvas canvas) {
mPath.reset();
int originY = 300;
int halfWaveLen = mItemWaveLength/2;
mPath.moveTo(-mItemWaveLength+dx,originY);
for (int i = -mItemWaveLength;i<=getWidth()+mItemWaveLength;i+=mItemWaveLength){
mPath.rQuadTo(halfWaveLen/2,-100,halfWaveLen,0);
mPath.rQuadTo(halfWaveLen/2,100,halfWaveLen,0);
}
mPath.lineTo(getWidth(),getHeight());
mPath.lineTo(0,getHeight());
mPath.close();
canvas.drawPath(mPath,mPaint);
}
private void bsrDraw(Canvas canvas) {
Paint paint = new Paint();
paint.setColor(Color.GREEN);
paint.setStyle(Paint.Style.STROKE);
canvas.drawPath(mPath,paint);
}
private void bsrTest(Canvas canvas) {
Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.GREEN);
Path path = new Path();
path.moveTo(100,300);
path.quadTo(200,200,300,300);
path.quadTo(400,400,500,300);
canvas.drawPath(path,paint);
}
private void test2(Canvas canvas) {
int paddingLeft = getPaddingLeft();
int paddingTop = getPaddingTop();
canvas.drawColor(Color.BLACK);
Paint paint = new Paint();
paint.setColor((Color.RED));
canvas.drawRect(new Rect( paddingLeft, paddingTop, getWidth() - paddingLeft, getHeight() - paddingTop),paint);
//保存的画布大小为全屏幕大小
canvas.save();
canvas.clipRect(new Rect(100 + paddingLeft, 100 +paddingTop, 800, 800));
canvas.drawColor(Color.GREEN);
//保存画布大小为Rect(100, 100, 800, 800)
canvas.save();
canvas.clipRect(new Rect(200 + paddingLeft, 200 +paddingTop, 700, 700));
canvas.drawColor(Color.BLUE);
//保存画布大小为Rect(200, 200, 700, 700)
canvas.save();
//剪切canvas,canvas本身位置不变,剩下的是截切内的区域,Rect是相对与整个屏幕的,而canvas是他剩余的不分并且位置不变(不回到左上角0点位置)
canvas.clipRect(new Rect(300 + paddingLeft, 300 +paddingTop, 600, 600));
//canvas平移
canvas.translate(-400,-400);
//剪切canvas,在canvas上面剪切的剩余不分和Rect取交集
// canvas.clipRect(new Rect(0 + paddingLeft, 0 +paddingTop, 700, 700));
// canvas.drawColor(Color.BLACK);
//保存画布大小为Rect(300, 300, 600, 600)
// canvas.save();//将当前的画布状态压入栈,会面可以取出这个栈来canvas
// canvas.restore();//弹出一个画布栈返回上一个栈来canvas translate scale rotate skew clipXXX drawXXXXX
// canvas.clipRect(new Rect(400, 400, 500, 500));
// canvas.drawColor(Color.WHITE);
//
// //将栈顶的画布状态取出来,作为当前画布,并画成黄色背景
// canvas.restore();
// canvas.drawColor(Color.YELLOW);
}
private void test1(Canvas canvas) {
canvas.translate(100, 100);
canvas.drawColor(Color.RED);//可以看到,整个屏幕依然填充为红色
Paint paint = new Paint();
paint.setColor(Color.GREEN);
canvas.drawRect(new Rect(-100, -100, 0, 0),paint);
canvas.scale(0.5f, 0.5f);
paint.setColor(Color.BLUE);
canvas.drawRect(new Rect(0, 0, 100, 100), paint);//缩放了
canvas.translate(200, 0);
canvas.rotate(30);
paint.setColor(Color.YELLOW);
canvas.drawRect(new Rect(0, 0, 100, 100), paint);//旋转了
canvas.translate(200, 0);
canvas.skew(.5f, .5f);//扭曲了
paint.setColor(Color.BLACK);
canvas.drawRect(new Rect(0, 0, 100, 100), paint);
// canvas.setMatrix(matrix);//Matrix的使用在后面在是。
}
}