Canvas
1、什么是canvas
直译是画布,本质其实是绘制图形的工具类。
2、什么时候生成的
ViewRootImpl类中的draw方法中
在drawSoftware方法中获得Canvas,使用的Surface中的lockCanvas方法,传入的参数为屏幕的宽高
Surface的LockCanvas又是调用的nativeLockCanvas方法
生成完成之后再调draw(Canvas canvas)
3、Canvas画图的过程
canvas.drawRect(r,mPaint);
所以说Canvas并不会绘制图像,实际工作交给了native层,具体执行对象是GPU
Matrix总结
说一下Matrix变换矩阵
说明一下为什么使用矩阵,位移,缩放等一堆属性都放在一个对象里,省的每一个都建一个对象。
scale是缩放,skew是错切,trans是平移,persp代表透视。rotare翻转则是改变的是scale,skew,trans三个的值。
计算方法
矩阵怎么改变一个点呢,比如说(x_0,y_0)
缩放变换xxxScale()
Scale变换是由MSACLE_X,和MSCALE_Y控制的,那么自然的,xxxScale()就是通过修改这两个值到达变换矩阵目的。
调用setScale(k_1,k_2)则是直接把A矩阵设置为:
错切变换xxxSkew()
调用setSkew(k_1,k_2),直接将A设置成:
平移变换xxxTranslate()
调用setTranslate(k_1,k_2),直接将A设置成:
旋转变换xxxRotate()
调用setRotate(a)会直接把矩阵设置为:
我们再来看set前缀pre前缀以及post前缀变换时的区别,先来看看官方API文档:
public boolean postTranslate (float dx, float dy)
Postconcats the matrix with the specified translation. M' = T(dx, dy) * M
public boolean preTranslate (float dx, float dy)
Preconcats the matrix with the specified translation. M' = M * T(dx, dy)
在图形学中,矩阵M右乘A,表示的是 A * M,而矩阵 M 左乘 A,则表示的是 M * A,一比较,我们可以看出,pre其实执行的就是右乘的操作,而post执行的就是左乘的操作。这是因为,在图像处理中,越靠近右边的矩阵越先执行,所以pre(也就是先的意思)所设置的矩阵T(Scale,Rotation也是一样的)就会先于其一开始设置的Scale执行,而post(后的意思)的因为是左乘,所以它会放在最左边,那么就会最后执行。这时你们肯定会问set呢?set前缀的方法首先会将该Matrix设置为对角矩阵,即相当于调用reset()方法,然后再设置该Matrix的变换矩阵。纯文字的讲解估计说的已经云里雾里了,举个栗子:
Matrix的初始值:
[sx, k1, 0]
[k2, sy, 0]
[0, 0, 1]
上面set后,再preTranslate(4, 5):
[sx, k1, 2][1, 0, 4] [sx, k1, sx*4+k1*5+2]
[k2, sy, 3][0, 1, 5]=[k2, sy, k2*4+sy*5+3]
[0, 0, 1][0, 0, 1] [0, 0, 1]
上面set后,再postTranslate(4, 5)后:
[1, 0, 4][sx, k1, 2] [sx, k1, 2+4]
[0, 1, 5][k2, sy, 3]=[k2, sy, 5+3]
[0, 0, 1][0, 0, 1] [0, 0, 1]
Canvas部分方法说明
Canvas里的drawRect、drawLine我就不说明了,比较简单 ,说一下Canvas.save()方法,restore()方法
Canvas.save(),简单理解就是保存画布,作用是将之前的所有已绘制的图像保存起来,让后续的操作就好像在一个新的图层上操作一样
Canvas.restore(),可以理解为合并图层操作,作用是将save()之后绘制的所有图像与sava()之间的图像进行合并
直接举个栗子
canvas.drawLine(0,0,100,100,paintCircle);
canvas.translate(200,200);
canvas.drawLine(0,0,100,200,paintCircle);
canvas.save();
canvas.drawLine(0,0,100,300,paintCircle);
效果如下
可以看出即使save之后切换到图层2了,canvas.translate(200,200);的效果还在,然后如果我把图层2起点移动回左上角,切换回图层1,回是什么效果呢
canvas.drawLine(0,0,100,100,paintCircle);
canvas.translate(200,200);
canvas.drawLine(0,0,100,200,paintCircle);
canvas.save();
canvas.translate(-200,-200);
canvas.drawLine(0,0,100,300,paintCircle);
canvas.restore();
canvas.drawLine(0,0,100,400,paintCircle);
canvas.restore();之后回到图层1,图层1并没有受到canvas.translate(-200,-200);的影响,如果我再save一下,新的图层2还是原来的图层2吗
canvas.drawLine(0,0,100,100,paintCircle);
canvas.translate(200,200);
canvas.drawLine(0,0,100,200,paintCircle);
canvas.save();
canvas.translate(-200,-200);
canvas.drawLine(0,0,100,300,paintCircle);
canvas.restore();
canvas.drawLine(0,0,100,400,paintCircle);
canvas.save();
canvas.drawLine(0,0,100,500,paintCircle);
可以看出再次save,又是一个新的图层2,可以理解为一个状态栈,save是入栈,restore是出栈,restore的时候会把画的图像合并入下边的图层
画个图加深理解
其他东西学到之后再补充