Android Canvas 绘图之 PorterDuffXfermode
来源:互联网 发布:java如何安装与卸载 编辑:程序博客网 时间:2024/04/30 07:05
本文参照 http://blog.csdn.net/iispring/article/details/50472485
概述
类 Android.graphics.PorterDuffXfermode 继承自 android.graphics.Xfermode。
当绘图时和前面的图案有重叠部分,为了设置重叠规则,需要用到 PorterDuffXfermode,需要将将其作为参数传给 Paint.setXfermode(Xfermode xfermode) 方法。
PorterDuffXfermode 这个类中的 Porter 和 Duff 是两个人名,这两个人在 1984 年一起写了一篇名为《Compositing Digital Images》 的论文。
下面开始介绍 PorterDuffXfermode 的使用。
示例一
在演示 Xfermode 之前,先看一下下面的例子
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int r = canvas.getWidth() / 3; // 设置背景色 canvas.drawARGB(255, 139, 197, 186); //绘制黄色的圆形 paint.setColor(0xFFFFCC44); canvas.drawCircle(r, r, r, paint); //绘制蓝色的矩形 paint.setColor(0xFF66AAFF); canvas.drawRect(r, r, r * 2.7f, r * 2.7f, paint); }
重写了 View 的 onDraw 方法,首先将 View 的背景色设置为绿色,然后绘制了一个黄色的圆形,然后再绘制一个蓝色的矩形,效果如下所示:
没有设置 Xfermode 的时候,后来绘制的图形就会覆盖之前绘制的图形!
示例二
下面我们使用 Xfermode 对上面的代码进行一下修改,修改后的代码如下所示:
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int r = canvas.getWidth() / 3; // 设置背景色 canvas.drawARGB(255, 139, 197, 186); //绘制黄色的圆形 paint.setColor(0xFFFFCC44); canvas.drawCircle(r, r, r, paint); //绘制蓝色的矩形 paint.setColor(0xFF66AAFF); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); canvas.drawRect(r, r, r * 2.7f, r * 2.7f, paint); }
效果如下:
先来讲一下 setXfermode 的绘制原理:在 canvas.drawRect() 之前 setXfermode,那么所绘制的矩形中的像素称作源像素(source,简称 src),所绘制的矩形在 Canvas 中对应位置的矩形内的像素称作目标像素(destination,简称 dst)。根据 Xfermode 的规则,ARGB 的值会重新计算。
本例中 Xfermode 是 PorterDuff.Mode.CLEAR,直接将目标像素的 ARGB 四个分量全置为 0,即 (0,0,0,0),即透明色,所以实际上绘制了一个透明的矩形。但是效果图为什么是白色的呢,因为屏幕本身是白色的。
示例三
示例二中显示的白色,如果想要显示透明色,我们需要将代码作如下修改:
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int r = canvas.getWidth() / 3; // 设置背景色 canvas.drawARGB(255, 139, 197, 186); int layerId = canvas.saveLayer(0, 0, canvas.getWidth(), canvas.getHeight(), null, Canvas.ALL_SAVE_FLAG); //绘制黄色的圆形 paint.setColor(0xFFFFCC44); canvas.drawCircle(r, r, r, paint); //绘制蓝色的矩形 paint.setColor(0xFF66AAFF); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); canvas.drawRect(r, r, r * 2.7f, r * 2.7f, paint); canvas.restoreToCount(layerId); }
效果如下:
我们将绘制圆形与矩形的代码放到了 canvas.saveLayer() 和 canvas.restoreToCount() 之间。
关于 canvas 绘图中的 layer 有以下几点需要说明:
Canvas 是支持图层 layer 渲染这种技术的,Canvas 默认就有一个 layer,当我们平时调用 Canvas 的各种
drawXXX() 方法时,其实是把所有的东西都绘制到 Canvas 这个默认的 layer 上面。我们还可以通过 canvas.saveLayer() 新建一个 layer,新建的 layer 放置在 canvas 默认 layer 的上部,当我们执行了 canvas.saveLayer() 之后,我们所有的绘制操作都绘制到了我们新建的 layer 上,而不是 canvas
默认的 layer。用 canvas.saveLayer() 方法产生的 layer 所有像素的 ARGB 值都是 (0,0,0,0),即 canvas.saveLayer()
方法产生的 layer 初始时时完全透明的。canvas.saveLayer() 方法会返回一个 int 值,用于表示 layer 的 ID,在我们对这个新 layer 绘制完成后可以通过调用 canvas.restoreToCount(layer) 或者 canvas.restore() 把这个 layer 绘制到 canvas 默认的 layer 上去,这样就完成了一个 layer 的绘制工作。
所以 CLEAR 操作时在新建的图层上面,背景色不再是 Activity 的背景色,变成了默认图层的背景色了。
一张被不经大脑疯传的神图
如果大家 Google 或百度 PorterDuffXfermode 相关的博文,大家肯定会看到下面这张神图,如下所示:
其实这张图有点问题,具体可以参照 http://blog.csdn.net/iispring/article/details/50472485
不同 Mode 的效果
PorterDuff.Mode.CLEAR, //清除PorterDuff.Mode.SRC, //只绘制源图PorterDuff.Mode.DST, //只绘制目标图像PorterDuff.Mode.SRC_OVER, //在目标图像的上方绘制源图像PorterDuff.Mode.DST_OVER, //在源图像的上方绘制目标图像PorterDuff.Mode.SRC_IN, //只在源图像和目标图像相交的地方绘制源图像PorterDuff.Mode.DST_IN, //只在源图像和目标图像相交的地方绘制目标图像PorterDuff.Mode.SRC_OUT, //只在源图像和目标图像不相交的地方绘制源图像PorterDuff.Mode.DST_OUT, //只在源图像和目标图像不相交的地方绘制目标图像PorterDuff.Mode.SRC_ATOP, //在源图像和目标图像相交的地方绘制源图像,在不相交的地方绘制目标图像PorterDuff.Mode.DST_ATOP, //在源图像和目标图像相交的地方绘制目标图像,在不相交的地方绘制源图像PorterDuff.Mode.XOR, //在源图像和目标图像重叠之外的任何地方绘制他们,而在重叠的地方不绘制任何内容PorterDuff.Mode.DARKEN, //变暗PorterDuff.Mode.LIGHTEN, //变亮PorterDuff.Mode.MULTIPLY, //正片叠底PorterDuff.Mode.SCREEN, //滤色PorterDuff.Mode.ADD, //饱和相加PorterDuff.Mode.OVERLAY //叠加
代码可见 https://github.com/teletian/Android/tree/master/PorterDuffXfermode
- Android Canvas 绘图之 PorterDuffXfermode
- Canvas绘图之PorterDuffXfermode
- Android中Canvas绘图之PorterDuffXfermode使用
- Android中Canvas绘图之PorterDuffXfermode的坑
- Android中Canvas绘图之PorterDuffXfermode使用及工作原理详解
- Android 中 Canvas 绘图之 PorterDuffXfermode 使用及工作原理详解
- Android中Canvas绘图之PorterDuffXfermode使用及工作原理详解
- Android中Canvas绘图之PorterDuffXfermode使用及工作原理详解
- Android中Canvas绘图之PorterDuffXfermode使用及工作原理详解
- Android 中 Canvas 绘图之 PorterDuffXfermode 使用及工作原理详解
- ANdroid绘图之Canvas
- android绘图之canvas
- Android:图形图像之使用Canvas,Paint绘图
- Android绘图基础之: Canvas 和 Paint
- 【canvas】Android Canvas绘图详解
- SWT之Canvas绘图
- Canvas绘图之旅
- 绘图之Canvas学习
- Preference使用总结
- linux 系统调用---ioctl
- 测试对于效率的提升都可以做些什么?
- 多播委托
- mssql单个用户与多个用户
- Android Canvas 绘图之 PorterDuffXfermode
- 工作线程(耗时操作)与UI线程实现异步更新
- 三星又推出新工具啦!Gear VR 可以兼容多个视频
- Android属性动画高阶用法-Interpolator,TypeEvaluatory以及贝塞尔曲线公式的使用
- java的第一天
- 判断一个矩阵中是否可以找到一条包含某个String的路径
- opencv(13)---图像滤波
- Xilinx ISE软件 模拟组合逻辑入门
- 基于IntelliJ IDEA开发Spark的Maven项目——Scala语言