Canvas方法进一步学习

canvas.save()

save方法是和restore方法成对出现的,save方法用来保存画布的状态,而restore方法用来恢复画布的状态,并将save和restore之间绘制的图像,合并到画布上。
当我们对画布进行旋转,缩放,平移等操作的时候其实我们是想对特定的元素进行操作,比如图片,一个矩形等,但是当你用canvas的方法来进行这些操作的时候,其实是对整个画布进行了操作,那么之后在画布上的元素都会受到影响,所以我们在操作之前调用canvas.save()来保存画布当前的状态,当操作之后取出之前保存过的状态,这样就不会对其他的元素进行影响。

代码段1:

1
2
3
4
5
6
7
8
9
10
public void draw() {   
Canvas canvas = sfh.lockCanvas();
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(bmp1, 0,0,paint);
canvas.save();
canvas.scale(5f, 5f);
canvas.restore();
canvas.drawBitmap(bmp2, 0,0,paint);
sfh.unlockCanvasAndPost(canvas);
}

代码段2:

1
2
3
4
5
6
7
8
public void draw() {   
Canvas canvas = sfh.lockCanvas();
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(bmp1, 0,0,paint);
canvas.scale(5f, 5f);
canvas.drawBitmap(bmp2, 0,0,paint);
sfh.unlockCanvasAndPost(canvas);
}

上面这两个代码片段中我们都假设有两张图片bmp1和bmp2,并且都画在画布上!那么代码段1和代码段2的不同:
代码段1中我们进行画布缩放的之前保存了画布状态,做了缩放操作之后又取出之前保存的状态,这样做是为了保证bmp2正常画出来不受到缩放的影响!代码段2里,画了bmp1后就执行了缩放操作,并且没有保存状态!紧接着画了bmp2,那么bmp2也会一样受到缩放的影响!

canvas.restore()

见canvas.save()方法中的介绍。

canvas.translate()

平移画布,更好的理解是:平移坐标系。原来画布的坐标原点是(0,0),当执行了translate(x,y)之后,之后的操作都是以(x,y)为坐标原点进行操作的。

canvas.roatate()

旋转画布,更好的理解是:旋转坐标系。

通过使用translate()方法和rotate方法可以方便我们进行开发,例子:画表盘。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
public class Clock extends View {

private int mHeight, mWidth;

public Clock(Context context) {
super(context);
}

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

public Clock(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

@Override
protected void onDraw(Canvas canvas) {
// 获取宽高参数
mWidth = getMeasuredWidth();
mHeight = getMeasuredHeight();
// 画外圆
Paint paintCircle = new Paint();
paintCircle.setStyle(Paint.Style.STROKE);
paintCircle.setAntiAlias(true);
paintCircle.setStrokeWidth(5);
canvas.drawCircle(mWidth / 2,
mHeight / 2, mWidth / 2, paintCircle);
// 画刻度
Paint painDegree = new Paint();
paintCircle.setStrokeWidth(3);
for (int i = 0; i < 24; i++) {
// 区分整点与非整点
if (i == 0 || i == 6 || i == 12 || i == 18) {
painDegree.setStrokeWidth(5);
painDegree.setTextSize(30);
canvas.drawLine(mWidth / 2, mHeight / 2 - mWidth / 2,
mWidth / 2, mHeight / 2 - mWidth / 2 + 60,
painDegree);
String degree = String.valueOf(i);
canvas.drawText(degree,
mWidth / 2 - painDegree.measureText(degree) / 2,
mHeight / 2 - mWidth / 2 + 90,
painDegree);
} else {
painDegree.setStrokeWidth(3);
painDegree.setTextSize(15);
canvas.drawLine(mWidth / 2, mHeight / 2 - mWidth / 2,
mWidth / 2, mHeight / 2 - mWidth / 2 + 30,
painDegree);
String degree = String.valueOf(i);
canvas.drawText(degree,
mWidth / 2 - painDegree.measureText(degree) / 2,
mHeight / 2 - mWidth / 2 + 60,
painDegree);
}
// 通过旋转画布简化坐标运算
canvas.rotate(15, mWidth / 2, mHeight / 2);
}
// 画圆心
Paint paintPointer = new Paint();
paintPointer.setStrokeWidth(30);
canvas.drawPoint(mWidth / 2, mHeight / 2, paintPointer);
// 画指针
Paint paintHour = new Paint();
paintHour.setStrokeWidth(20);
Paint paintMinute = new Paint();
paintMinute.setStrokeWidth(10);
canvas.save();
canvas.translate(mWidth / 2, mHeight / 2);
canvas.drawLine(0, 0, 100, 100, paintHour);
canvas.drawLine(0, 0, 100, 200, paintMinute);
canvas.restore();
}
}

效果图:
此处输入图片的描述

canvas.scale()

对画布进行缩放。

Canvas缩放有以下两个方法:

1
2
public void scale (float sx, floatsy) ;
public final void scale (float sx,float sy, float px, float py);

sx,sy分别为画布x轴和y轴的缩放比例,小于1的时候时缩小,大于一的时候是放大,缩放效果是对之后绘制的图形生效,并不会影响缩放之前绘制的图像,关于其使用建议阅读:Android Canvas 缩放(Scale)

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class CanvasSave extends View {

private Paint mPaint;

/**
* 圆的宽度
*/
private int mCircleWidth = 3;

private int width = 0;
private int height = 0;

public CanvasSave(Context context) {
this(context, null);
}

public CanvasSave(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public CanvasSave(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint = new Paint();
}

@Override
protected void onDraw(Canvas canvas) {

mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.CYAN);
canvas.drawRect(0,0,100,100,mPaint);
canvas.save();
canvas.scale(2.5f,2.5f);
mPaint.setColor(Color.BLACK);
canvas.drawRect(0,0,100,100,mPaint);
canvas.restore();
mPaint.setColor(Color.YELLOW);
canvas.drawRect(0,0,200,200,mPaint);


}

}

效果图:
此处输入图片的描述

示例代码:
Clock.java
CanvasSaveScale.java

参考链接:

canvas.save() canvas.restore() 作用

Android中canvas.save()和canvas.restore()的使用

Android Canvas的save(),saveLayer()和restore()浅谈

Android Canvas 缩放(Scale)

Android Canvas 方法总结

android绘图canvas的sava、restore、rotate以及若干问题,canvas绘图的理解

canvas变换

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器