Canvas的基本使用——常用的绘制方法介绍

Canvas直面意思是画布,其实是一个封装了很多绘制方法的工具类。
绘制图像有四大基本的要素:

  1. 一个用来保存像素的Bitmap。
  2. 一个用来执行绘制操作的工具类Canvas。
  3. 绘制的东西,如指明画直线,画文字以及其他各种我们想绘制的东西。
  4. 绘制用的画笔Paint。

一、 Canvas基本Api介绍:
1、绘画用到的API:

画背景:

/**
     *把整个画布用指定的颜色填充
     * @param r 红色值
     * @param g 绿色值
     * @param b 蓝色值
     */
public void drawRGB(int r, int g, int b)
//同上,只是加上了alpha透明度
public void drawARGB(int a, int r, int g, int b)
public void drawColor(@ColorInt int color)//同上
/**
     * 把整个画布根据指定的模式用指定的颜色填充
     * @param color 颜色值
     * @param mode  详细看PorterDuff.Mode
     */
    public void drawColor(@ColorInt int color, @NonNull PorterDuff.Mode mode)

/**
     * 使用指定的画笔,绘制一个尽可能大的矩形,即填充画布
     * @param paint The paint used to draw onto the canvas
     */
public void drawPaint(@NonNull Paint paint)

drawPaint方法需要注意的是,Paint画笔需要指定颜色一个带有透明度的颜色值,才能用指定的颜色值填充画布,如果没有指定颜色值,那么通过此方法填充的将是黑色。

Paint paint = new Paint();
paint.setColor(0xaadc2e07);//如果没有指定颜色,那么画布就变成黑色了
canvas.drawPaint(paint);//画笔整个变为浅红色

下面继续介绍绘画Api:

**

画点:

**

/**
* 在指定的左边x,y处画一个点,点的大小与Paint设置的setStrokeWidth有关,如果不设置线宽,无法绘制点
*/*
public void drawPoint(float x, float y, @NonNull Paint paint);
/** 
 * 参数1:多个点,每两个值为一个点。最后个数不够两个的值,忽略。 
 * [x0 y0 x1 y1 x2 y2 ...]
 */  
public void drawPoints(@Size(multiple=2) @NonNull float[] pts, @NonNull Paint paint);

/**
     *从点坐标数组pts中offset位置开始取count个数值,然后在画布上画出这些点
     * @param pts  点坐标数组,一个点2个值 [x0 y0 x1 y1 x2 y2 ...]
     * @param offset 从pts数组offset位置开始取值
     * @param count  在pts数组总共取多少个数值,offset+count<=pts.length
     * @param paint  画笔
     */
public void drawPoints(@Size(multiple=2) float[] pts, int offset, int count,
            @NonNull Paint paint)

如:

Paint paint = new Paint();
paint.setColor(0xaadc2e07);
float fp[]=new float[]{100,100,100,250,100,400,100,550};
paint.setStrokeWidth(100);
canvas.drawPoints(fp,3,4,paint);//从坐标点数组fp中脚标为3的地方开始取值,总共取4个值出来,即fp[3],fp[4],fp[5],fp[6]。

效果如下:
这里写图片描述
可以看到这里画出来的点是直角的,而不像我们印象中的点都是圆的,这是因为Paint画笔的影响。试想一下,如果我们的笔头是方的,那么画(就像盖章一样)出来的点,那也是方的,而如果我们的笔头是圆的,那么画出来的点也就是圆的了。通过Paint的setStrokeCap方法可以设置画笔笔帽样式。

Paint paint = new Paint();
paint.setColor(0xaadc2e07);
float fp[]=new float[]{100,100,100,250,100,400,100,550};
paint.setStrokeWidth(100);
paint.setStrokeCap(Paint.Cap.ROUND);//圆角
canvas.drawPoints(fp,3,4,paint);

效果:
这里写图片描述

针对setStrokeCap方法做几点说明:

  • Paint有个setStrokeCap方法可以设置所画线段的时候两个端点的形状,即所画线段的帽端的形状,在下面讲到drawLine方法时会详细说明,其实setStrokeCap方法也会影响所画点的形状。Paint的setStrokeCap方法可以有三个取值:Paint.Cap.BUTT、Paint.Cap.ROUND和Paint.Cap.SQUARE。
  • 默认情况下Paint的getStrokeCap的返回值是Paint.Cap.BUTT,默认画出来的点就是一个正方形,上图第一个点即是用BUTT作为帽端画的。
  • 我们可以调用setStrokeCap方法设置Paint的strokeCap为Paint.Cap.ROUND时,画笔画出来的点就是一个圆形,上图即是用ROUND作为帽端画的。
  • 调用调用setStrokeCap方法设置Paint的strokeCap为Paint.Cap.SQUARE时,画笔画出来的电也是一个正方形,与用BUTT画出来的效果在外观上相同

画线:

/**
     * 根据指定的起始点坐标,画一条直线
     *
     * @param startX 起始点x坐标
     * @param startY 起始点y坐标
     * @param paint  画笔
     */
public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint);

public void drawLines(@Size(multiple=4) @NonNull float[] pts, @NonNull Paint paint);

/**
     *与drawPoints方法类似
     * @param pts  直线坐标点 [x0 y0 x1 y1 x2 y2 ...]
     * @param offset  坐标偏移值
     * @param count   从pts中取多少个值
     * @param paint    画笔
     */
public void drawLines(@Size(multiple=4) @NonNull float[] pts, int offset, int count,
            @NonNull Paint paint)

画矩形:

 /**
     * 根据Rect指定的值画矩形,RectF与Rect的区别在于RectF存float型的坐标数据
     *
     * @param r        指定的矩形区域
     * @param paint    画笔
     */
public void drawRect(@NonNull Rect r, @NonNull Paint paint);
public void drawRect(@NonNull RectF rect, @NonNull Paint paint);
/**
     * 由指定的矩形的四个顶点画矩形
     * @param left   The left side of the rectangle to be drawn
     * @param top    The top side of the rectangle to be drawn
     * @param right  The right side of the rectangle to be drawn
     * @param bottom The bottom side of the rectangle to be drawn
     * @param paint  The paint used to draw the rect
     */
public void drawRect(float left, float top, float right, float bottom, @NonNull Paint paint)

画椭圆:

/**
* 在指定的左边区域内画椭圆
*/
public void drawOval(@NonNull RectF oval, @NonNull Paint paint);
public void drawOval(float left, float top, float right, float bottom, @NonNull Paint paint)

画圆:

/**
     * 根据指定的圆心坐标和半径画圆
     * @param cx     圆心x坐标
     * @param cy     圆心y坐标
     * @param radius 圆半径
     * @param paint  画笔
     */
    public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint)

画圆弧(扇形):

/**
 * 根据指定的起始角度在指定的区域内画出指定角度的圆弧或者扇形(如果画笔的mPaint.setStyle(Paint.Style.FILL);则画出来的是扇形,且useCenter为true);以指定的矩形区域中心点为圆心,画内切圆弧。
* @param oval   画圆弧的区域
* @param startAngle 画圆弧的起始角度,钟表3点钟方向为0度,逆时针方向为负值,顺时针方向为正值
* @param sweepAngle 画多少角度的圆弧
* @param useCenter 如果为false:只有一个纯弧线,为true:闭合的边
* @param paint     画笔
*/
public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter,l Paint paint);
/**
*同上
*/
public void drawArc(float left, float top, float right, float bottom, float startAngle,float sweepAngle, boolean useCenter, Paint paint)

如:

RectF r = new RectF(100, 100, 400, 800);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.BLUE);
canvas.drawRect(r, mPaint);
mPaint.setColor(Color.RED);
canvas.drawArc(r, -90, 90f, false, mPaint);//如果指定区域是一个正方形,则画出来的是圆形弧(或圆),如果是长方形,则画出的是椭圆弧(或椭圆)

效果如下:
这里写图片描述

画内切椭圆:

RectF r = new RectF(100, 100, 400, 800);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.BLUE);
canvas.drawRect(r, mPaint);
mPaint.setColor(Color.RED);
canvas.drawArc(r, 0, 360f, false, mPaint);//在指定的局域r里面,画出一个内切圆

效果图:
这里写图片描述

画封闭的圆弧:

RectF r = new RectF(100, 100, 400, 800);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.BLUE);
canvas.drawRect(r, mPaint);
mPaint.setColor(Color.RED);
canvas.drawArc(r, -90, 90f, true, mPaint);//画封闭的圆弧

效果如下:
这里写图片描述

画圆角矩形:

/**
* 画圆角矩形
* @param rect  矩形区域
* @param rx    x轴圆角半径
* @param ry    y轴圆角半径
* @param paint 画笔
*/
public void drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint);
public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
            @NonNull Paint paint)

画图片:

/*
 * @param bitmap 需要绘制的图片
 * @param left   开始绘制图片的左上角的x坐标
 * @param top    开始绘制图片的左上角的y坐标
 * @param paint  画笔
     */
public void drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint);

/*
 * @param bitmap 绘制的图片
 * @param src   见下面解释
 * @param dst    
 * @param paint 画笔
     */
public void drawBitmap(Bitmap bitmap,Rect src,RectF dst,Paint paint);
public void drawBitmap(Bitmap bitmap,Rect src,Rect dst,
            @Nullable Paint paint);
/**
  * 根据指定的矩阵绘制图片
  * @param bitmap 需要绘制的图片
  * @param matrix 矩阵
  * @param paint  画笔
  */
public void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint)

该方法有两个功能:
1.只绘制原有bitmap对象的一部分。
2.还可以将要绘制的bitmap缩放到指定的区域。

  • 只绘制原有bitmap对象的一部分 :
    我们知道Bitmap是一个矩形,其是有宽度和高度的,也就说以bitmap对象本身作为坐标系(原点在bitmap左上角),我们可以构建一个Rect对象,如果满足left为0,top为0,right为bitmap的宽度,bottom为bitmap的高度,那么就说名我们要绘制整个Bitmap。但是有时候我们只想绘制Bitmap的一部分,例如我们上面的图中所示,我们想只绘制Android图像的头部区域怎么办呢?办法是我们构建一个Rect对象,定义我们要绘制Bitmap的哪些部位。 比如我们通过代码srcRect.bottom = (int)(0.33 * bitmap.getHeight())指定了我们只绘制bitmap对象头部1/3的位置,即Android图像的头部,这样我们用该指定的srcRect绘制bitmap时只绘制了其头部位置。需要特别注意的是,srcRect中left、top、right、bottom的值都是以Bitmap本身的局部坐标系为基础的。
  • 将要绘制的bitmap缩放到指定的区域 :
    有时候我们需要将原有的bitmap进行放大或缩小,如上图所示,我们将原有图片放大了,这怎么做呢?我们需要指定RectF类型的参数dstRectF,以便告诉Android将srcRect中定义的bitmap缩放到哪里。即Android会将srcRect中定义的bitmap缩放到dstRectF区域范围内。需要注意的是,此处的dstRecF是绘图坐标系中的坐标,不是Bitmap本身的局部坐标系。我们在代码中保证了dstRecF的长宽比与srcRect中的长宽比相同,这样不会导致图片长宽比例变形,效果见上图中的第二个放大的图形。

画文字:

/**
  * 画文字
  * @param text  需要绘制的文字
  * @param x     绘制文字起始点x坐标
  * @param y     绘制文字的基线(baseline)y坐标
  * @param paint 画笔
  */
public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) ;

/**
* Draw the text, with origin at (x,y), using the specified paint.
* The origin is interpreted based on the Align setting in the paint.
*
* @param text  绘制的文字内容
* @param start 开始脚标
* @param end   结束脚标
* @param x     x轴偏移量,即文字开始绘制时的x轴坐标
* @param y     baseline的y坐标
* @param paint 画笔
*/
public void drawText(@NonNull String text, int start, int end, float x, float y, Paint paint);
public void drawText(@NonNull char[] text, int index, int count, float x, float y,
            @NonNull Paint paint);//同上,只是文字变成了数组

关于baseline的y坐标的计算情参考另外一篇博客:Canvas的drawText方法详解

沿路径画文字:

/**
* 沿路径画文字,如沿着圆圈的外边画一串文字等
* @param text     绘制的文字
* @param path     沿着画文字的路径
* @param hOffset  与路径起始点的水平偏移距离
* @param vOffset  与路径中心的垂直偏移量
* @param paint    画笔
*/
public void drawTextOnPath(char[] text, int index, int count,  Path path,float hOffset, float vOffset,Paint paint);
/**
* 同上
*/
public void drawTextOnPath(String text, Path path, float hOffset,float vOffset, @NonNull Paint paint);

实例代码:

Paint paint = new Paint();

Path path = new Path();
path.addCircle(500, 500, 300, Path.Direction.CW);//顺时针方向绘制圆
paint.setStrokeWidth(20);
paint.setColor(Color.BLUE);
paint.setStyle(Paint.Style.STROKE);
canvas.drawPath(path, paint);

paint.reset();

paint.setColor(Color.RED);
paint.setTextSize(40);
canvas.drawTextOnPath("世界和平!!!", path, 0, -10, paint);

实现的效果图:

这里写图片描述

总结:至此Canvas常用的绘制方法就介绍完了,Canvas中还有其他常用的Api方法,如Canvas的旋转,缩放等,在接下来的博客中,会继续介绍。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值