(十)Canvas 的基本使用
来源:互联网 发布:cad中网络接口怎么画 编辑:程序博客网 时间:2024/06/05 17:04
版权声明:本文为博主原创文章,未经博主允许不得转载。
本文纯个人学习笔记,由于水平有限,难免有所出错,有发现的可以交流一下。
一、概述
Canvas 我们经常把它理解为画板,但是,实际上 Canvas 是一个封装类,它包含了四个东西:
1、画板:用来保存像素的bitmap
2、画布或者画纸: Canvas 在 Bitmap 上进行绘制操作 —- (Layer—saveLayer操作时,新建一个透明的画布图层)
3、绘制的东西
4、绘制的画笔 Paint
二、Canvas 的基本方法
1.画直线
canvas.drawLine(0, 0, 100, 100, paint);
drawLine(float startX, float startY, float stopX, float stopY, Paint paint)
startX: 起始点 x 坐标
startY :起始点 y坐标
stopX: 结束点 x 坐标
stopY :结束点 y坐标
paint :画笔
2.画多条直线
float []pts = {0,0,100,100,200,200,300,300}; canvas.drawLines(pts, paint);
drawLines(float[] pts, Paint paint)
pts : 直线的端点数组,每 4 个点为一条直线
drawLines(float[] pts, int offset, int count, Paint paint)
pts : 直线的端点数组,每 4 个点为一条直线
offset : 跳过的数据个数,跳过的数据不参与直线绘制
count : 实际参与绘制的数据个数
3.画点
canvas.drawPoint(50, 50, paint);
drawPoint(float x, float y, Paint paint)
x : 点的 x 坐标
y : 点的 y 坐标
4.画多个点
float []pts = {0,0,100,100,200,200,300,300}; canvas.drawPoints(pts, paint);
drawPoints(float[] pts, Paint paint)
pts : 点的坐标数组,每 2个点为一个点
drawPoints(float[] pts, int offset, int count, Paint paint)
pts : 点的坐标数组,每 2个点为一个点
offset : 跳过的数据个数,跳过的数据不参与点绘制
count : 实际参与绘制的数据个数
5.画矩形
RectF r = new RectF(100, 100, 400, 500); canvas.drawRect(r, paint);
canvas.drawRectdrawRect(100, 100, 400, 500, paint);
drawRect(RectF rect, Paint paint)
rect : 矩形区域
drawRect(Rect r, Paint paint)
r : 矩形区域
drawRect(float left, float top, float right, float bottom, Paint paint)
left : 左边的 x 坐标
top :上边的 y 坐标
right : 右边的 x 坐标
bottom : 底边的 y 坐标
注:RectF 和 Rect 主要区别是精度,RectF 使用的是 float, Rect 使用的是 int。
6.画圆角矩形
RectF r = new RectF(100, 100, 400, 500); canvas.drawRoundRect(r, 30, 30, paint);
canvas.drawRoundRect(100, 100, 400, 500, 30, 30, paint);
drawRoundRect(RectF rect, float rx, float ry, Paint paint)
rect : 矩形区域
rx:x方向上的圆角半径。
ry:y方向上的圆角半径。
drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, Paint paint)
left : 左边的 x 坐标
top :上边的 y 坐标
right : 右边的 x 坐标
bottom : 底边的 y 坐标
rx:x方向上的圆角半径。
ry:y方向上的圆角半径。
7.画圆
canvas.drawCircle(300, 300, 200, paint);
drawCircle(float cx, float cy, float radius, Paint paint)
cx : 圆心的x坐标
cy : 圆心的y坐标
radius : 圆的半径
8.画椭圆
RectF r = new RectF(100, 100, 400, 500); canvas.drawOval(r, paint);
canvas.drawOval(100, 100, 400, 500, 30, 30, paint);
drawOval(RectF oval, Paint paint)
oval : 外切矩形区域
drawOval(float left, float top, float right, float bottom, Paint paint)
left : 外切矩形左边的 x 坐标
top :外切矩形上边的 y 坐标
right : 外切矩形右边的 x 坐标
bottom :外切矩形 底边的 y 坐标
9.画圆弧
RectF r = new RectF(100, 100, 400, 500); canvas.drawArc(r, 0, 90, true, paint);
canvas.drawArc(100, 100, 400, 500, 0, 90, true, paint);
drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)
oval : 圆弧所在椭圆外切矩形
startAngle : 圆弧的起始角度(0 为 x轴正方向)
sweepAngle : 圆弧的角度
useCenter:是否显示半径连线,true表示显示圆弧与圆心的半径连线,false表示不显示
drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, Paint paint)
left : 圆弧所在外切矩形左边的 x 坐标
top :圆弧所在外切矩形上边的 y 坐标
right : 圆弧所在外切矩形右边的 x 坐标
bottom :圆弧所在外切矩形 底边的 y 坐标
startAngle : 圆弧的起始角度(0 为 x轴正方向)
sweepAngle : 圆弧的角度
useCenter:是否显示半径连线,true表示显示圆弧与圆心的半径连线,false表示不显示
把 useCenter 改为 false:
10.画路径
Path path = new Path(); //画笔落笔的位置 path.moveTo(100, 100); //移动 path.lineTo(200, 100); path.lineTo(200, 200); path.cubicTo(250, 200, 400, 250, 450, 400); path.close(); canvas.drawPath(path, paint);
drawPath(Path path, Paint paint)
path : 路径
path 部分不在这边细讲。
三、Canvas 画区域
Canvas 除了画常用的形状之外,还能画 Region ,它表示的 Canvas 图层上的一块封闭的区域。由于区域是不规则的,所以在绘制的时候会被切割成多个矩形,通过迭代进行绘制。
Paint paint = new Paint(); paint.setColor(Color.RED); //样式必须设为 STROKE,否则看不出效果 paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(2); RectF r = new RectF(100, 100, 600, 800); Path path = new Path(); path.addOval(r, Path.Direction.CCW); //创建一块矩形的区域 Region region = new Region(100, 100, 600, 800); Region region1 = new Region(); //path的椭圆区域和矩形区域进行交集 region1.setPath(path, region); //结合区域迭代器使用(得到图形里面的所有的矩形区域) RegionIterator iterator = new RegionIterator(region1); Rect rect = new Rect(); //通过迭代,进行区域的绘制 while (iterator.next(rect)) { canvas.drawRect(rect, paint); }
区域的叠加规则
区域叠加规则枚举类 Op 的源码:
public enum Op { DIFFERENCE(0), INTERSECT(1), UNION(2), XOR(3), REVERSE_DIFFERENCE(4), REPLACE(5); Op(int nativeInt) { this.nativeInt = nativeInt; } /** * @hide */ public final int nativeInt; }
效果图中 A 为调用者, B 为叠加上来的区域。
op(Rect r, Op op)
r: 叠加上去的矩形
op : 叠加规则
op(int left, int top, int right, int bottom, Op op)
left : 叠加上去的矩形左边的 x 坐标
top :叠加上去的矩形上边的 y 坐标
right : 叠加上去的矩形右边的 x 坐标
bottom :叠加上去的矩形 底边的 y 坐标
op : 叠加规则
op(Region region, Op op)
region: 叠加上去的区域
op : 叠加规则
四、Canvas 坐标系
Paint paint = new Paint(); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(10); RectF r = new RectF(0, 0, 400, 500); paint.setColor(Color.GREEN); canvas.drawRect(r, paint); //平移 canvas.translate(50, 50); paint.setColor(Color.BLUE); canvas.drawRect(r, paint);
上方代码先绘制一个矩形,然后进行平移操作,后再次绘制一个矩形。在 translate(50, 50) 里平移的是 Canvas 的绘图坐标系,而不是 Canvas。我们可以稍微证明一下。
Paint paint = new Paint(); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(10); RectF r = new RectF(0, 0, 400, 500); paint.setColor(Color.GREEN); canvas.drawRect(r, paint); //平移 canvas.translate(50, 50); canvas.drawColor(Color.YELLOW); paint.setColor(Color.BLUE); canvas.drawRect(r, paint);
在平移后给画布填充颜色,发现整个屏幕都充满,说明平移的不是画布。
Canvas里面牵扯两种坐标系:Canvas 自己的坐标系、绘图坐标系。
1.Canvas 自己的坐标系
它就在View的左上角,做坐标原点往右是X轴正半轴,往下是Y轴的正半轴,有且只有一个,唯一不变。
2..Canvas 绘图坐标系
它不是唯一不变的,它与Canvas的Matrix有关系,当Matrix发生改变的时候,绘图坐标系对应的进行> > 改变。
用画直线的方法把平移前后的坐标系画出来。可以发现平移之后坐标系变了。
RectF r = new RectF(0, 0, 400, 500); paint.setColor(Color.GREEN); canvas.drawRect(r, paint); canvas.drawLine(0,0,canvas.getWidth(),0,paint);// X 轴 canvas.drawLine(0,0,0,canvas.getHeight(),paint);// Y 轴 canvas.translate(50, 50); paint.setColor(Color.BLUE); canvas.drawRect(r, paint); canvas.drawLine(0,0,canvas.getWidth(),0,paint);// X 轴 canvas.drawLine(0,0,0,canvas.getHeight(),paint);// Y 轴
继续进行旋转45度。
RectF r = new RectF(0, 0, 400, 500); paint.setColor(Color.GREEN); canvas.drawRect(r, paint); canvas.drawLine(0,0,canvas.getWidth(),0,paint);// X 轴 canvas.drawLine(0,0,0,canvas.getHeight(),paint);// Y 轴 canvas.translate(50, 50); paint.setColor(Color.BLUE); canvas.drawRect(r, paint); canvas.drawLine(0,0,canvas.getWidth(),0,paint);// X 轴 canvas.drawLine(0,0,0,canvas.getHeight(),paint);// Y 轴 canvas.rotate(45); paint.setColor(Color.YELLOW); canvas.drawLine(0,0,canvas.getWidth(),0,paint);// X 轴 canvas.drawLine(0,0,0,canvas.getHeight(),paint);// Y 轴
结论:绘制坐标的变化跟矩阵 Matrix 有关。Matrix又是通过我们设置translate、rotate、scale、skew来进行改变的
3.Canvas 绘图坐标系的重置
Canvas 绘制坐标系的变化过程是不可逆的,只能通过 save 和 restore 方法来保存和还原变化操作
RectF r = new RectF(0, 0, 400, 500); paint.setColor(Color.GREEN); canvas.drawRect(r, paint); canvas.drawLine(0,0,canvas.getWidth(),0,paint);// X 轴 canvas.drawLine(0,0,0,canvas.getHeight(),paint);// Y 轴 canvas.save(); canvas.translate(50, 50); paint.setColor(Color.BLUE); canvas.drawRect(r, paint); canvas.drawLine(0,0,canvas.getWidth(),0,paint);// X 轴 canvas.drawLine(0,0,0,canvas.getHeight(),paint);// Y 轴 canvas.restore(); canvas.rotate(45); paint.setColor(Color.YELLOW); canvas.drawLine(0,0,canvas.getWidth(),0,paint);// X 轴 canvas.drawLine(0,0,0,canvas.getHeight(),paint);// Y 轴
在第一次变化坐标前 save,绘制坐标系后 restore, 再次进行坐标变化是从最开始的坐标系进行变化。说明第一次变化后,坐标系重置还原了。
五、Canvas的状态保存—状态栈、Layer栈
1.状态栈 – save、 restore 方法
1.只是保存和还原变换操作 Matrix 以及 Clip 剪裁,
2.可以通过 restoretoCount 直接还原到对应栈的保存状态。
3.不是真正的图层关系
2.Layer栈
1.真正的图层关系,saveLayer 的时候都会新建一个透明的图层(离屏 Bitmap-离屏缓冲),并且会将saveLayer 之前的一些 Canvas 操作延续过来
2. 后续的绘图操作都在新建的layer上面进行
3.当我们调用restore 或者 restoreToCount 时会更新到对应的图层和画布上
saveLayer 可以实现所有 save 的实现效果。save 只是在栈中保存 Matrix 以及 Clip 剪裁的变换记录,当开始绘制的时候,根据栈中保存的变换记录得出最终的绘制坐标,从而进行绘制。saveLayer 是把前面的操作保存成一个 Layer 存入栈中,再新建一个 Layer,后续绘制在新的 Layer 上进行,新绘制的 Layer 可以根据 saveLayer 的时候传的参数进行选择保存上一个 Layer 的哪些 Matrix 以及 Clip 剪裁的变换。
目前个人除了在使用 Xfermode 的时候,用 save() 方法的话,原先绘制的背景会对浑噩结果造成影响,所以要用 saveLayer()。其他地方使用暂时没有发现区别。
- (十)Canvas 的基本使用
- canvas的基本使用
- Canvas的基本使用
- android canvas的基本使用
- android Canvas的基本使用
- canvas学习一之canvas的基本使用
- Canvas的基本介绍和使用
- Canvas基本使用
- HTML5>canvas基本使用
- Android Canvas 基本使用
- Canvas基本使用
- scala 学习(十)——类的基本使用
- canvas的基本用法
- Canvas基本矩形的
- Canvas的基本用法
- 第二十一篇:UITableView的基本使用
- Canvas的基本使用——常用的Api方法介绍(二)
- Canvas的基本使用——常用的Api方法(2):clip*裁剪方法
- ROS教程(十):创建ROS消息和ROS服务
- 一位10年Java工作经验的架构师聊Java和工作经验
- MATLAB学习笔记 学习总结归纳(第二周)
- Java8新特性学习
- java-base64编码和解码
- (十)Canvas 的基本使用
- 图片切分小程序和图片重新调整大小兼重命名小程序
- Intellij Idea如何像Eclipse一样的Tab快捷键可以直接跳出括号
- arm64-v8a 百度地图
- BZOJ 4666 小z的胡话
- JS基本类型与无法定义的属性
- 视频录制(一)—mediaRecorder介绍
- Mac下关于——你不能拷贝项目“”,因为它的名称太长或包括的字符在目的宗卷上无效。文件的删除
- Python之爬虫