本篇文章介绍Canvas。
首先了解下什么是Canvas,从字面上翻译为“画布”,本质上是一个绘制图形的工具类。
为什么说是工具类来看看源码中
##Canvas
public boolean clipRect(int left, int top, int right, int bottom) { //1
return nClipRect(mNativeCanvasWrapper, left, top, right, bottom,
Region.Op.INTERSECT.nativeInt);
}
private static native boolean nClipRect(long nativeCanvas,//2
float left, float top, float right, float bottom, int regionOp);
注释1 为Canvas绘制矩形的方法 注释2其实这里调用的native层的方法来创建图形。不止是这个方法Canvas中调用绘制图形的API都是调用native层的方法来创建图形,所以Canvas可以理解为native层图形绘制封装出来的工具类。其具体的绘制由GPU去完成。
Canvas的坐标系:
安卓中默认的坐标零点位于屏幕的左上角,向下为y轴正方向、向右为x轴的正方向
图形分析:
canvas.png
在Canvas中拥有两个坐标系
第一个坐标系为Canvas坐标系其特性为一经确定就不会改变
第二个坐标系为绘制坐标系其特性为再修改坐标后,这个过程是不可逆的
第一坐标系其实挺好理解的就像控件位置一但确定就不会到处跑位置就固定了
第二坐标系的不可逆的意思是改了坐标后这个坐标的零点就发生了变化,在不改变坐标的情况下是回不去的。
Canvas除了图形绘制外的主要方法:
canvas.save();//1
canvas.restore();//2
canvas.translate();//3
canvas.rotate();//4
注释1:
可以理解为保存画布,作用是将之前的所有已绘制的图像保存起来,让后续的操作就好像在一个新的图层上操作一样
注释2:
可以理解为合并图层操作,作用是将save()之后绘制的所有图像与save()之前的图像进行合并
注释3:
绘制坐标平移
注释4:
绘制坐标翻转
Matrix变换矩阵
RectF r = new RectF(0, 0, 400, 400);//1
canvas.drawRect(r, mPaint);//2
Matrix matrix = canvas.getMatrix();//3
Log.i(TAG, matrix.toString());//4
1创建矩形2绘制矩形3得到变换矩阵4打印变换矩阵这里你会看到Matrix的值为3个数组
当绘制坐标平移或者翻转的时候Matrix变换矩阵的值将发生变化也就是3个数组的值。
计算方式如下
matrix1.png
matrix2.png
Canvas图层的概念:
statu.png
1.状态栈
如上图save、restore方法来保存和还原变换操作matrix以及Clip剪裁,也可以通过restoretoCount直接还原到对应栈的保存状态其实这也相当于操作这些图层。
2.Layer栈
saveLayer的时候都会新建一个透明的图层(离屏Bitmap-离屏缓冲),并且会将saveLayer之前的一些Canvas操作延续过来,后续的绘图操作都在新建的layer上面进行,当我们调用restore 或者 restoreToCount 时 更新到对应的图层和画布上
canvas的save方法和savelayer最大的区别在于创建的图层。sacelayer创建出来的图层能看到底下图层。而save创建图层不能看到底部的图层。
总结:
Canvas里面有两种坐标系——Canvas自己坐标系和绘制坐标系。Canvas坐标系它就在View的左上角,做坐标原点往右是X轴正半轴,往下是Y轴的正半轴,有且只有一个,唯一不变。绘制坐标系它不是唯一不变的,它与Canvas的Matrix有关系,当Matrix发生改变的时候,绘图坐标系对应的进行改变, 同时这个过程是不可逆的(save和restore方法来保存和还原变化操作), Matrix又是通过我们设置translate、rotate、scale、skew来进行改变的。
Canvas的状态保存——状态栈和layer栈。状态栈--save、 restore方法来保存和还原变换操作Matrix以及Clip剪裁 也可以通过restoretoCount直接还原到对应栈的保存状态。Layer栈saveLayer的时候都会新建一个透明的图层(离屏Bitmap-离屏缓冲),并且会将saveLayer之前的一些Canvas操作延续过来,后续的绘图操作都在新建的layer上面进行, 当我们调用restore 或者 restoreToCount 时 更新到对应的图层和画布上
本篇文章到这里就结束了!
作者:Dean_Xu
原创博客,请注明转载处....