Android的Canvas各函数全解析

目录:


1、save
2、 saveLayer
3、restore
4、Canvas的矩阵变换
5、 clipPath详解
     5.1  DIFFERENCE
     5.2  REVERSE_DIFFERENCE
     5.3  INTERSECT
     5.4  UNION
     5.5  XOR
     5.6  REPLACE
6、 clipPath详解
7、 clipRegion详解
8、 setDrawFilter
9、 drawRGB
10、 drawColor
11、混合模式
12、 drawPoint and  drawLine
13、 drawRect, drawOval,drawCycle, drawArc,drawBoundRect
14、 drawBitmap
15、drawText、drawTextOnPath、drawPosText
15.1 drawText
15.2 drawTextOnPath
15.3 drawPosText


1、save

  • save(),将会保存matrix及clip操作,保存的操作(translate,scale,rotate,skew,concat or clipRect,clipPath

  • save(int saveFlags) 可选参数为 MATRIX SAVE_FLAGCLIP_SAVE_FLAG
     注意,返回值表示可认为是相应的id,表示那一次保存。



2、saveLayer

  • 功能和save相似,但是不同于save直接作用于canvas,saveLayer是作用于某一个图层。google官方建议,如果在save能满足条件的情况下,尽量适用save,因为saveLayer会造成大于2次的渲染,造成不必要的资源浪费。如果在view的hardware layer(LAYER_TYPE_HARDWARE)能使用的情况下,尽可能的使用,会比saveLayer有更好的效果。
      【例子2-1】实际应用中,出现过想使用混合模式去除相较的部分,但是由于两个图片都是有透明度的,造成混合后效果不理想,这个时候可以采用saveLayer将其中一个使用不透明的替代,混合之后再加入的canvas中

表2-1 表示各个标记位属于对哪个函数有效

标记 适用
MATRIX_SAVE_FLAG
save
saveLayer
CLIP_SAVE_FLAG
save
saveLayer
HAS_ALPHA_LAYER_SAVE_FLAG saveLayer
FULL_COLOR_LAYER_SAVE_FLAG saveLayer
CLIP_TO_LAYER_SAVE_FLAG saveLayer
ALL_SAVE_FLAG
save
saveLayer


3、restore

     对应于之前的save进行压栈操作,这里进行相应的出栈操作。
     restoreToCount(int)表示弹出至相应的保存(如果相应的保存不在top,会将其他在他之后操作的图层全部pop出来)


4、Canvas的矩阵变换

  • translate(float x, float y) 将canvas进行平移
  • scale(float sx, float sy) 为基准(0,0)为基准进行缩放
  • scale(float sx, float sy, float px, float py)为基准(px,py)为基准进行缩放
  • rotate(float degrees) 为基准(0,0)进行画布旋转
  • rotate(float degrees, float px, float py) 为基准(px,py)进行画布旋转
  • skew(float sx, float sy) 交错处理
  • concat(@Nullable Matrix matrix)   Pre-concatenating a to b means setting a = b × a. 
  • setMatrix(@Nullable Matrix matrix) 直接设置覆盖原先矩阵
  • getMatrix(@NonNull Matrix ctm) 获取画布矩阵


5、 clipRect详解

  • clipRect(@NonNull RectF rect, @NonNull Region.Op op)
  • clipRect(@NonNull Rect rect, @NonNull Region.Op op)
  • clipRect(@NonNull RectF rect)
  • clipRect(@NonNull Rect rect)
  • clipRect(float left, float top, float right, float bottom, @NonNull Region.Op op)
  • clipRect(float left, float top, float right, float bottom)
  • clipRect(int left, int top, int right, int bottom)
     上述函数看着有很多选择,其实归结起来就两个参数,第一参数是给定具体剪切的 范围,第二个参数是给定具体的截取完之后的区域的 填充模式
     范围这里参数很好理解,填充模式有如下6种,如下表:
表 5-1 填充模式及说明

模式定义 说明
DIFFERENCE A-B区域
INTERSECT A与B的交集
UNION A与B的并集
XOR (A∪B) - (A∩B)
REVERSE_DIFFERENCE B-A区域
REPLACE B将完全显示,如果和A有交集覆盖A,也就是B

注:假设剪切前为A,剪切区域为B

    
上图中绿色为剪切区域A,右边红色区域为B,中间深红色为两者的相交区域
    

     5.1 DIFFERENCE

     表示将绘制出A-B的区域,如下图

     5.2 REVERSE_DIFFERENCE

     将绘制出B-A的区域,如下图
     

     5.3 INTERSECT

               A与B的交集( 默认模式)

     5.4 UNION

          A与B的并集,

     5.5 XOR

              (A∪B) - (A∩B)
    

     5.6 REPLACE

          B将完全显示,如果和A有交集覆盖A,也就是整个B



6、 clipPath详解

     和5的clipRect类似,唯一的区别是一个是矩阵边框,另外一个是以path为边框。
      或者说,起始Rect是有四条line组成的,也就是说,Rect仅仅是path的一种特殊形式。 Path可以实现,line,quad(二次贝塞尔曲线),cubic(三次贝塞尔曲线),cycle, rect。
  • clipPath(@NonNull Path path, @NonNull Region.Op op)
  • clipPath(@NonNull Path path)
               下图是通过3条直线和一条cubic曲线划出来的区域。
     



7、 clipRegion详解(API 21已经废弃)

     和clipPath和clipRect的区别是,当前画布的矩阵变换对clipPath和clipRect有效,但对clipRegion无效。在5.5的实验中,可以看到相应的图,如果什么都不变换,直接将clipRect变为clipRegion则会出现如下的图:

从上图可以猜测,我们当前view的canvas其实已经做过相应的matrix变换了,所以我们采用region则直接忽略这种变换,直接以屏幕左上角作为原点。(注,蓝色区域是采用drawRect画出来的,所以会收到canvas的影响)

8、 setDrawFilter

    这个没怎么查到相应的资料,唯一类似的参考地址为: http://m.blog.csdn.net/article/details?id=47151293  
   文章中说道,唯一使用的方式是进行canvas的抗锯齿的配置,代码如下:
mDrawFilter = new PaintFlagsDrawFilter( 0 , Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); canvas.setDrawFilter(mDrawFilter); // 从canvas层面去除绘制时锯齿


9、 drawRGB

  • drawRGB(int r, int g, int b)
  • drawARGB(int a, int r, int g, int b)
     这两个函数很好理解,直接在画布上绘制相应颜色,后面一个函数表示可以绘制alpha的值。


10、 drawColor

     参考网址:
  • drawColor(@ColorInt int color)
  • drawColor(@ColorInt int color, @NonNull PorterDuff.Mode mode)
     和9的drawRGB直接就是调用了drawColor函数。这里第二个函数带有一个混合模式选择,将在11小节中介绍。


11、混合模式



属性 说明 颜色 对比
CLEAR 清理相应的颜色 [0, 0]  
SRC 显示上层绘制图片 [Sa, Sc]  
DST 显示下层绘制图片 [Da, Dc]  
SRC_OVER 正常绘制显示,上下层绘制叠盖。(后者覆盖前者) [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc]SRC的区别是,存在alpha的时候,SRC完全显示src,而SRC_OVER则是存在混合
DST_OVER
上下层都显示。下层居上显示。

[Sa + (1 - Sa)*Da, Rc = Dc + (1 - Da)*Sc]  
SRC_IN    取两层绘制交集。显示上层。 [Sa + (1 - Sa)*Da, Rc = Dc + (1 - Da)*Sc]  
DST_IN   取两层绘制交集。显示下层。 [Sa * Da, Sa * Dc]  
SRC_OUT  取上层绘制非交集部分。 [Sa * (1 - Da), Sc * (1 - Da)]  
DST_OUT  取下层绘制非交集部分。 [Da * (1 - Sa), Dc * (1 - Sa)]  
SRC_ATOP  取下层非交集部分与上层交集部分 [Da, Sc * Da + (1 - Sa) * Dc]  
DST_ATOP  取上层非交集部分与下层交集部分 [Sa, Sa * Dc + Sc * (1 - Da)]  
XOR   异或:去除两图层交集部分 [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]  
DARKEN   取两图层全部区域,交集部分颜色加深 [Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)]  
LIGHTEN   取两图层全部,点亮交集部分颜色 [Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)]  
MULTIPLY   取两图层交集部分叠加后颜色 [Sa * Da, Sc * Dc]  
SCREEN  取两图层全部区域,交集部分变为透明色 [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc]  
ADD   Saturate(S + D)  
OVERLAY   Saturate(S + D)  


图11-1 存在透明度情况下,左图为采用SRC模式,右图才作用SRC_OVER模式。


图11-2 在图片为 非透明的情况下各模式的效果图

图11-3 在图片为 透明的情况下各模式的效果图

 


12、 drawPoint and drawLine

  • drawPoints(@Size(multiple=2) float[] pts, int offset, int count,@NonNull Paint paint)
  • drawPoints(@Size(multiple=2) @NonNull float[] pts, @NonNull Paint paint)
  • drawPoint(float x, float y, @NonNull Paint paint)

  • drawLine(float startX, float startY, float stopX, float stopY, @NonNull Paint paint)
  • drawLines(@Size(min=4,multiple=2) float[] pts, int offset, int count, Paint paint)
  • drawLines(@Size(min=4,multiple=2) @NonNull float[] pts, @NonNull Paint paint)
     这两者区别不是很大,画点和画直线罢了。


13、 drawRect,drawOval,drawCycle, drawArc,drawBoundRect,drawPath


图12-1 drawRect、drawOval、drawCycle、drawArc集合图


图12-2 drawArc的四种形式

  • drawRect可以绘制矩形,设置paint的模式,就可绘制出空心或者实心的矩形
  •  drawOval 可以绘制圆或者椭圆
  • drawCycle 绘制圆行(和drawOval不同是,drawOval是采用Rect的形式,定了4个点,然后画相应的图形,而drawCycle是采用给定圆心坐标以及半径来进行绘制)
  • drawArc 相当于在drawOval的基础上,可以绘制圆弧,(booleanuseCenter) 这个参数设为fasle为图12-2左边两种形式,如果设为true则为右边两种形式。
  •  drawBoundRect 这个是画的如下 12-3这样的图,给定一个RectF, 还有两个参数,rx, ry,决定了4个角的弧度。如图12-4右边图形,ry=2*rx,可以看到不同的角的弯度。
  • drawPath 这个可以完成你能想象的到的图形,效果如图12-5。
     
图12-3 drawBoundRect图

图 12-4 drawBoundRect图(ry=2*rx)

    

图 12-5 drawPath图(左为Fill,右为Stroke)


14、 drawBitmap

  • drawBitmap(Bitmap bitmap, float left, float top, Paint paint)
            >>>> left, top 表示开始画bitmap的起始位置
  • drawBitmap(Bitmap bitmap,  Rect src,  RectF dst, Paint paint)
  • drawBitmap(Bitmap bitmap,  Rect src,  Rect dst, Paint paint)
            >>>> src表示对图片的剪切,dst表示绘制的区域(如果绘制区域比绘制内容小,则绘制相应的内容;如果绘制区域比绘制内容大,则将绘制内容进行延伸)


15、drawText、drawTextOnPath、drawPosText


15.1 drawText

  • drawText(char[] text, int index, int count, float x, float y, Paint paint)
  • drawText(String text, float x, float y, Paint paint)
  • drawText(String text, int start, int end, float x, float y, Paint paint) 
  • drawText(CharSequence text, int start, int end, float x, float y, Paint paint)
     drawText 有三种形式,总结起来就一种,第一参数(有些使用char[], index, count三个参数表示)为需要绘制的Text的内容,第二、三个参数(x,y)为表示为开始绘制的点,需要注意的一点是,text的基准点不是绘制其他图形的时候的左上角那个点,而是baseline所代表的位置。如图15-1所示,其中origin,便是参数是x,y所代表的点。

图 15-1 text的各种参数

15.2 drawTextOnPath

  • drawTextOnPath(@NonNull char[] text, int index, int count, @NonNull Path path,
            float hOffset, float vOffset, @NonNull Paint paint)
  • drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset,
            float vOffset, @NonNull Paint paint)
      path表示以path作为text的基准线(baseLine)进行绘制, hoffet表示横向的偏离(沿着path)第一个开始绘制的位置如图15-2中的第一行第三列的效果,如果值设为负,如图15-2中的第一行第二列的效果,会出现重叠。其次,绘制text的范围为path,所以突然text太长, 尾部为重叠,15-2中的第一行第一列的效果。
voffet表示纵向的偏离,如图15-2的第二行所示。

图15-2 drawTextOnPath的各种形式
     

15.3 drawPosText

          根据传入的pos参数绘制text,效果如下图:

图 15-3 drawPosText




















©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页