Canvas的基本使用——常用的Api方法(2):clip*裁剪方法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011118524/article/details/78290791

Canvas的裁剪所用到的方法主要是clipRect,clipPath,clipRegion三类方法。

clipRect方法:

clipRect方法提供了七个重载的方法实现,如:
这里写图片描述

参数介绍如下:

  • rect:Rect对象,用于定义裁剪区的范围,Rect和RectF功能类似,精度和提供的方法不同而已
  • left:矩形裁剪区的左边位置
  • top:矩形裁剪区的上边位置
  • right:矩形裁剪区的右边位置
  • bottom:矩形裁剪区的下边位置
  • op:裁剪区域的组合方式

上述四个值可以是浮点型或者整型。

使用示例:
1、没有op参数的clipRect方法,即普通的画布裁剪方法。

canvas.drawColor(Color.BLUE);//裁剪之前
//裁剪
Rect rect = new Rect(100, 100, 400, 400);
canvas.clipRect(rect);
canvas.drawColor(Color.RED);//红色就去就是剪裁出来的画布,通过剪裁之后,所有的操作都只能在剪裁区域内绘制。

效果如下:
这里写图片描述

2、有op参数的clipRect方法:
有op参数的裁剪方法,会根据op参数的不同,裁剪出来的画布也会不一样,这里先对op参数做一个介绍,看源码可以知道, Region.Op是一个枚举类型,总共有6个值可供选择,如下:

  • DIFFERENCE:是第一次不同于第二次的部分显示出来
  • REPLACE:是显示第二次的
  • REVERSE_DIFFERENCE: 是第二次不同于第一次的部分显示
  • INTERSECT:交集显示
  • UNION:全部显示
  • XOR:补集 就是全集的减去交集生育部分显示

下面通过具体的实例来验证一下不同值的具体含义:
(1)DIFFERENCE,显示第一次不同于第二次的部分显示出来

canvas.drawColor(Color.GRAY);//原始画布填充一个灰色的默认背景
canvas.save();
canvas.drawRect(new Rect(100, 100, 200, 200), mStrokePaint);//画一个黄色框,方便识别
canvas.clipRect(110, 110, 190, 190);//第一次裁剪
canvas.clipRect(130, 130, 170, 170, Region.Op.DIFFERENCE);//第二次裁剪
canvas.drawColor(Color.WHITE);//剪裁过后,在画布上执行绘制操作
canvas.restore();

效果图:
这里写图片描述
由效果图可以看出来,经过两次裁剪之后,可进行绘制的画布就只有白色区域了,即裁剪得到的可操作画布即为白色区域。
如果代码中的第一次裁剪不执行,即注释掉的话,效果如下:可以看出来最终的效果是在整个画布中挖掉了一块,被挖掉的这一块是无法执行绘制的:
这里写图片描述
灰色部分为去掉的部分,白色部分为留下来的画布,白色区域是可以进行绘制的。

(2)REPLACE:显示第二次的裁剪的结果

canvas.drawColor(Color.GRAY);//原始画布填充一个灰色的默认背景
canvas.save();
canvas.drawRect(new Rect(100, 100, 200, 200), mStrokePaint);//画一个黄色框,方便识别
canvas.clipRect(110, 110, 190, 190);//第一次裁剪
canvas.drawColor(Color.BLUE);//第一次裁剪后,给画布填充一个蓝色的背景,
canvas.clipRect(130, 130, 170, 170, Region.Op.REPLACE);//第二次裁剪
canvas.drawColor(Color.WHITE);//剪裁过后,在画布上执行绘制操作,绘制的内容都在这个白色的区域内,超出白色区域的绘制不显示,即无效。
mPaint.setColor(Color.RED);
canvas.drawLine(100, 100, 200, 200, mPaint);//画一条红色的对角线
canvas.restore();

效果图:
这里写图片描述
白色区域为两次裁剪过后留下来的区域,即经过两次裁剪之后的可绘制区域。如红色的对角线坐标是从蓝色的左上角开始画,到蓝色的右下角结束的,但最终显示的只有白色区域的这部分,超出的部分绘制无效。

(3)REVERSE_DIFFERENCE: 是第二次不同于第一次的部分显示

canvas.save();
canvas.drawRect(new Rect(100, 100, 200, 200), mStrokePaint);//画一个黄色框,方便识别
canvas.clipRect(110, 110, 190, 190);//第一次裁剪
canvas.drawColor(Color.BLUE);
canvas.clipRect(150, 150, 250, 250, Region.Op.REVERSE_DIFFERENCE);//第二次裁剪
canvas.drawColor(Color.WHITE);//剪裁过后,在画布上执行绘制操作
mPaint.setColor(Color.RED);
canvas.drawLine(100, 100, 250, 250, mPaint);
canvas.restore();

效果图:
这里写图片描述
由上图可以看出,Region.Op.REVERSE_DIFFERENCE模式下,最终保留下来的画布是白色区域,蓝色区域和蓝色与白色相交的区域都被去掉了,即是经过两次裁剪后的不可以绘制的区域。红色线是从蓝色区域的左上角画到白色区域的右下角。

(4)INTERSECT:交集显示
与(3)代码一样,只是在第二次裁剪的是,把最后一个参数改成了Region.Op.INTERSECT,

canvas.save();
canvas.drawRect(new Rect(100, 100, 200, 200), mStrokePaint);//画一个黄色框,方便识别
canvas.clipRect(110, 110, 190, 190);//第一次裁剪
canvas.drawColor(Color.BLUE);
canvas.clipRect(150, 150, 250, 250, Region.Op.INTERSECT);//第二次裁剪
canvas.drawColor(Color.WHITE);//剪裁过后,在画布上执行绘制操作
mPaint.setColor(Color.RED);
canvas.drawLine(100, 100, 250, 250, mPaint);
canvas.restore();

实现的效果如下:
这里写图片描述
由上图可以看出,Region.Op.INTERSECT模式下,最终保留下来的画布第一次与第二次裁剪的交集部分被保留了下来,即途中的是白色区域,而不相交的区域都被去掉了。

(5)UNION:全部显示

与(3)代码一样,只是在第二次裁剪的是,把最后一个参数改成了Region.Op.UNION,

canvas.save();
canvas.drawRect(new Rect(100, 100, 200, 200), mStrokePaint);//画一个黄色框,方便识别
canvas.clipRect(110, 110, 190, 190);//第一次裁剪
canvas.drawColor(Color.BLUE);
canvas.clipRect(150, 150, 250, 250, Region.Op.UNION);//第二次裁剪
canvas.drawColor(Color.WHITE);//剪裁过后,在画布上执行绘制操作
mPaint.setColor(Color.RED);
canvas.drawLine(100, 100, 250, 250, mPaint);
canvas.restore();

实现的效果图如下:
这里写图片描述
由上图可以看出,Region.Op.UNION模式下,最终保留下来的画布是第一次与第二次所有的裁剪部分被保留了下来,即途中的是白色区域,即两次裁剪区域相加。可以看出,第一次裁剪后填充的蓝色没有了,因为在第二次裁剪结束后,给可绘制区域重新填充了白色,所以蓝色被替换了。

(6)XOR:补集 就是全集的减去交集生育部分显示:
与(3)代码一样,只是在第二次裁剪的是,把最后一个参数改成了Region.Op.XOR,

canvas.save();
canvas.drawRect(new Rect(100, 100, 200, 200), mStrokePaint);//画一个黄色框,方便识别
canvas.clipRect(110, 110, 190, 190);//第一次裁剪
canvas.drawColor(Color.BLUE);
canvas.clipRect(150, 150, 250, 250, Region.Op.XOR);//第二次裁剪
canvas.drawColor(Color.WHITE);//剪裁过后,在画布上执行绘制操作
mPaint.setColor(Color.RED);
canvas.drawLine(100, 100, 250, 250, mPaint);
canvas.restore();

实现的效果图如下:
这里写图片描述
由上图可以看出,Region.Op.XOR模式下,最终保留下来的画布是第一次与第二次裁剪不相交的部分被保留了下来,即图中的是白色区域,而相交的区域被去掉了。

clipPath方法介绍:

通过clipPath方法裁剪画布,即根据Path指定的路径(即区域)裁剪出一块画布出来。

canvas.save();
canvas.translate(10, 160);
canvas.clipRect(new Rect(0, 0, 100, 100));//第一次裁剪画布
canvas.drawColor(Color.BLUE);//第一次裁剪画布后,为画布填充蓝色背景
Path mPath = new Path();//new一个Path对象,
//canvas.clipPath(mPath); // makes the clip empty
mPath.addCircle(50, 50, 50, Path.Direction.CCW);//添加一个半径为50的圆
canvas.clipPath(mPath, Region.Op.REPLACE);//第二次裁剪画布,最后一个参数与clipRect方法的一样,参考上面
drawContent(canvas);//绘制内容
canvas.restore();

实现的效果图如下:
这里写图片描述
由上图可以看出,白色的圆所在的区域是可绘制区域,而蓝色部分为不可绘制区域。clipPath和clipRect本质没什么区别,clipRect裁剪方法裁剪的区域比较单一,只能是矩形区域,而clipPath方法裁剪的区域更加丰富,基本上是你指定什么区域,就裁剪什么区域,相比较而言,clipPath更加的灵活和丰富。
对于Path类的使用还会专门写一篇博客来介绍,这里就不过多的介绍了。

clipRegion方法:

clipRegion方法用到了Region类:
Region,中文意思即区域的意思,它表示的是canvas图层上的某一块封闭的区域。

注意:
与clipRect和clipPath要使用当前的matrix进行变换不同。clipRegion不会进行转换。也就是说canvas的matrix对clipRegion没有影响。

Paint paint = new Paint();
canvas.scale(0.5f, 0.5f);

paint.setColor(Color.BLUE);
canvas.drawRect(new Rect(0, 0, 300, 300), paint);//矩形实际大小为150*150

canvas.save();
canvas.clipRect(new Rect(300, 300, 600, 600));//裁剪区域实际大小为150*150
canvas.drawColor(Color.RED);
canvas.restore();

canvas.clipRegion(new Region(new Rect(400, 0, 700, 300)));//裁剪区域实际大小为300*300
canvas.drawColor(Color.YELLOW);

实现的效果图如下:
这里写图片描述

可以看到,Canvas的变换 对clipRegion没有作用。
这里推荐一篇写的不错的博客:Android 2D Graphics学习(二)、Canvas篇2、Canvas裁剪和Region、RegionIterator,这里就有对Region和clipRegion的详细介绍。

猜你喜欢

转载自blog.csdn.net/u011118524/article/details/78290791