Canvas的理解

Canvas

1、什么是canvas

    直译是画布,本质其实是绘制图形的工具类。

2、什么时候生成的

ViewRootImpl类中的draw方法中

drawSoftware方法

在drawSoftware方法中获得Canvas,使用的Surface中的lockCanvas方法,传入的参数为屏幕的宽高


生成Canvas

Surface的LockCanvas又是调用的nativeLockCanvas方法 


Surface中调用底层方法

生成完成之后再调draw(Canvas canvas)

draw(Canvas canvas)

3、Canvas画图的过程

canvas.drawRect(r,mPaint);


Canvas中


BaseCanvas


BaseCanvas

所以说Canvas并不会绘制图像,实际工作交给了native层,具体执行对象是GPU 

Matrix总结

说一下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矩阵设置为:


setScale

错切变换xxxSkew()

调用setSkew(k_1,k_2),直接将A设置成:


setSkew

平移变换xxxTranslate()

调用setTranslate(k_1,k_2),直接将A设置成:


setTranslate

旋转变换xxxRotate()

调用setRotate(a)会直接把矩阵设置为:


setRotate

我们再来看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);

效果如下


效果1

可以看出即使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);


效果2

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);


效果3

可以看出再次save,又是一个新的图层2,可以理解为一个状态栈,save是入栈,restore是出栈,restore的时候会把画的图像合并入下边的图层

画个图加深理解


状态栈

其他东西学到之后再补充

你可能感兴趣的:(Canvas的理解)