canvas可以看做是一台打印机,bitmap是好比纸,paint是墨水,打印机使用不同的墨水在不同的纸上绘制,而canvas本身自带有纸了,但你也可以指定它在你指定的纸上绘制。
1.canvas.save()方法:
这个方法调用后会保存调用这个方法前的状态,相当于调用了这个方法后重新铺上了一个新的图层,之后的绘制会在新的图层,不会对之前的绘制造成影响。
2.canvas.restore(); 方法:
调用了save的方法后在新的图层里绘制,绘制完后调用这个方法会重新回到save之前的图层。所以这里与save的方法是一起使用的,就类似与图层栈的入栈与出栈,所以这个方法调用的次数必须要比save调用的次数少。 这两个方法的作用,举个例子:绘画了一个部分后,想对接下来的绘画具有缩放效果,为了不影响前面的,调用是save的方法,然后使用缩放的方法绘制,绘制后下想返回,就调用这个方法,那么之后的绘制就没有缩放的效果了。
3.canvas.rotate 方法:
这个可以使图层旋转,好处举个例子:画个时钟的刻度,你只要指定一个刻度的绘画线就可以了,然后选择角度继续一样的绘画就可以了,与ps绘画相似。
4.canvas.translate 方法:
这个可以使图层移动,举个例子,你想从某个位置上划线,你不知道终点坐标,只指定划线长度,那么将起点移动到这个位置,那么相当于从(0,0)位置上划线,结合save与restore的方法,可以使绘画很方便。
举个例子:
int w = getWidth();
int h = getHeight();
Paint p = new Paint();
p.setColor(Color.parseColor("#00bcd4"));
canvas.drawCircle(w / 2, h / 2, 150, p);
p.setColor(Color.WHITE);
canvas.drawCircle(w / 2, h / 2, 140, p);
p.setColor(Color.BLACK);
p.setStrokeWidth(4);
for (int i = 0; i < 12; i++) {
canvas.drawLine(w / 2 - 140, h / 2, w / 2 - 130, h / 2, p);
canvas.rotate(360 / 12, w / 2, h / 2);
}
canvas.save();
canvas.translate(w / 2, h / 2);
canvas.drawLine(0, 0, 20, 0, p);
canvas.drawLine(0,0,0,50,p);
canvas.restore();
效果如下:
4.结合Matrix的使用
Matrix的对图像的处理可分为四类基本变换:
Translate 平移变换
Rotate 旋转变换
Scale 缩放变换
Skew 错切变换
Translate 平移变换
Rotate 旋转变换
Scale 缩放变换
Skew 错切变换
5.canvas.clipRect
canvas裁剪:有6种裁剪,分别是:
Region.Op.DIFFERENCE 显示裁剪区以外的部分
测试代码:
<pre name="code" class="java">canvas.drawColor(Color.GRAY);
Paint p=new Paint();
canvas.clipRect(50, 50, 200, 300, Region.Op.DIFFERENCE );
p.setAntiAlias(true);
Rect rect=new Rect();
rect.set(50, 50, 200, 400);
p.setColor(Color.RED);
canvas.drawRect(rect, p);
p.setColor(Color.parseColor("#00bcd4"));
canvas.drawCircle(getWidth() / 2, getHeight() / 2, 150, p);
Region.Op.REPLACE 是显示裁剪区以内的部分
测试代码:
<pre name="code" class="java"> canvas.clipRect(50, 50, 200, 300, Region.Op.REPLACE );
p.setAntiAlias(true);
Rect rect=new Rect();
rect.set(50, 50, 200, 400);
p.setColor(Color.RED);
canvas.drawRect(rect, p);
p.setColor(Color.parseColor("#00bcd4"));
canvas.drawCircle(getWidth() / 2, getHeight() / 2, 150, p);
效果如下:
Region.Op.REVERSE_DIFFERENCE 两次裁剪区域的的差集部分:
Paint p=new Paint();
canvas.clipRect(50, 50, 200, 300, Region.Op.REVERSE_DIFFERENCE );
canvas.clipRect(50, 50, 100, 200, Region.Op.REVERSE_DIFFERENCE );
p.setAntiAlias(true);
Rect rect=new Rect();
rect.set(50, 50, 200, 400);
p.setColor(Color.RED);
canvas.drawRect(rect, p);
p.setColor(Color.parseColor("#00bcd4"));
canvas.drawCircle(getWidth() / 2, getHeight() / 2, 150, p);
Region.Op.INTERSECT 两次裁剪区域的交集部分:
代码如下:
<pre name="code" class="java">canvas.drawColor(Color.GRAY);
Paint p=new Paint();
canvas.clipRect(50, 50, 200, 300, Region.Op.INTERSECT );
canvas.clipRect(50, 50, 100, 200, Region.Op.INTERSECT );
p.setAntiAlias(true);
Rect rect=new Rect();
rect.set(50, 50, 200, 400);
p.setColor(Color.RED);
canvas.drawRect(rect, p);
p.setColor(Color.parseColor("#00bcd4"));
canvas.drawCircle(getWidth() / 2, getHeight() / 2, 150, p);
效果如下:
Region.Op.UNION 两次裁剪的并集
Region.Op.XOR 补集 就是全集的减去交集生育部分显示
6.canvas.clipPath 方法:
注意的是,这里的path应该是一个封闭的路径。
代码如下:
Bitmap b= BitmapFactory.decodeResource(getResources(), R.mipmap.pic);
canvas.drawColor(Color.GRAY);
Paint p=new Paint();
Path path = new Path();
path.addCircle(getWidth() /2, getHeight()/2,155, Path.Direction.CW);
canvas.clipPath(path,Region.Op.INTERSECT);
p.setAntiAlias(true);
Rect rect=new Rect();
rect.set(50, 50, 200, 400);
p.setColor(Color.RED);
canvas.drawRect(rect, p);
p.setColor(Color.parseColor("#00bcd4"));
canvas.drawCircle(getWidth() / 2, getHeight() / 2, 150, p);
效果如下: