阅读 191

关于Canvas的用法,这些都只是基操

Canvas的用法总结

我们先来看一下Canvas类的介绍:Canvas是用来主持绘画操作的类,如果想要画些东西,你需要4个组件:一个保存像素的Bitmap,一个主持绘画操作的Canvas(往Bitmap写东西),一个绘制的基本元素(例如Rect,Path,Text,Btimap),一支画笔(用来描述绘画的颜色与风格)。

英语水平有限...

从Canvas类的描述来看,Canvas是用来做绘画操作的,那我们来看一下Canvas有哪些绘画操作(以下绘制的Paint默认为stroken风格):

Canvas的绘制功能

drawArc:绘制圆弧
/**
 * @param 圆弧的整个矩形范围
 * @param 开始角度
 * @param 扫描多少角度
 * @param 是否包含中心点
 * @param 绘制的画笔
 */
canvas?.drawArc(RectF(0f, 0f, 500f, 300f), 30f, 90f, false, mPaint)
复制代码

drawARGB:绘制颜色
/**
 * @param alpha值0-255
 * @param 红色值0-255
 * @param 绿色值0-255
 * @param 蓝色值0-255
 */
canvas?.drawARGB(255, 255, 123, 87)
复制代码

drawBitmap:绘制位图
/**
 * @param 要绘制的bitmap
 * @param 开始绘制的left
 * @param 开始绘制的right
 * @param 绘制的paint
 */
canvas?.drawBitmap(bitmap, 100f, 100f, mPaint)
复制代码

/**
 * @param 要绘制的bitmap
 * @param 绘制源的矩形(确定要绘制的图片的子集,绘制图片的部分信息,为null时绘制整个bitmap)
 * @param 绘制目标的矩形(通过缩放拉伸,将绘制信息绘制到目标区域)
 * @param 绘制的paint
 */
canvas?.drawBitmap(bitmap, Rect(0, 0, bitmap.width / 2, bitmap.height / 2), Rect(50, 50, 500, 500), mPaint)
复制代码

drawBtimap还有个高级用法,drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint),这个涉及到Matrix时在说

drawCircle:绘制圆
/**
 * @param 绘制圆中心x坐标
 * @param 绘制圆中心y坐标
 * @param 绘制圆的半径
 * @param 绘制的paint
 */
canvas?.drawCircle(100f, 100f, 50f, mPaint)
复制代码

drawColor:绘制颜色
/**
 * @param 绘制圆中心x坐标
 * @param 绘制圆中心y坐标
 * @param 绘制圆的半径
 * @param 绘制的paint
 */
canvas?.drawColor(Color.GRAY)
复制代码

这个很简单,跟drawARGB是差不多的,不过他还有一个重载方法,需要传入一个PorterDuff.Mode,我们用下面一张图来看看PorterDuff.Mode不同模式的效果

这个模式在paint里面会比较常用,我们在paint里面在实际使用看看效果

drawLine:绘制直线
/**
 * @param 起始点x坐标
 * @param 起始点y坐标
 * @param 终结点x坐标
 * @param 终结点y坐标
 * @param 绘制的paint
 */
canvas?.drawLine(0f, 0f, 100f, 300f, mPaint)
复制代码

/**
 * @param 需要绘制的数组,必须是4的倍数,跟drawLine设置点一样
 * @param 绘制的paint
 */
canvas?.drawLines(floatArrayOf(0f, 0f, 100f, 300f, 50f, 50f, 200f, 300f), mPaint)
复制代码
drawOval:绘制椭圆
/**
 * @param 绘制椭圆的矩形
 * @param 绘制的paint
 */
canvas?.drawOval(RectF(0f, 0f, 300f, 100f), mPaint)
复制代码

drawRect:绘制矩形

绘制矩形参数跟绘制椭圆一样,很简单

drawPoint:绘制点

绘制点需要制定点的xy坐标就可以

drawText:绘制文字
/**
 * @param 绘制的文字
 * @param 起始点x
 * @param 文字的基准线y
 * @param 绘制的paint
 */
canvas?.drawText("kevinxie", 10f, 200f, mPaint)
复制代码

drawPath:绘制路径
val path = Path()
path.lineTo(0f, 100f)
path.lineTo(100f, 100f)
/**
 * @param 绘制的路径
 * @param 绘制的paint
 */
canvas?.drawPath(path, mPaint)
复制代码

canvas的绘画操作大致就这么多了,canvas还有变形的功能

Canvas的变形功能

translate:平移
canvas?.drawBitmap(bitmap, null, Rect(50, 50, 500, 500), mPaint)
/**
 * @param x方向平移的距离
 * @param y方向平移的距离
 */
canvas?.translate(100f, 100f)
canvas?.drawBitmap(bitmap, null, Rect(50, 50, 500, 500), mPaint)
复制代码

scale:缩放
canvas?.drawBitmap(bitmap, null, Rect(50, 50, 500, 500), mPaint)
/**
 * @param x方向平移的距离
 * @param y方向平移的距离
 */
canvas?.scale(0.8f, 0.8f, 600f, 600f)
canvas?.drawBitmap(bitmap, null, Rect(50, 50, 500, 500), mPaint)
复制代码

rotate:旋转
canvas?.drawBitmap(bitmap, null, Rect(50, 50, 500, 500), mPaint)
/**
 * @param 旋转的角度
 * @param 旋转中心点的x左边点
 * @param 旋转中心点的y左边点
 */
canvas?.rotate(30f, 700f, 700f)
canvas?.drawBitmap(bitmap, null, Rect(50, 50, 500, 500), mPaint)
复制代码

skew:错切
canvas?.drawBitmap(bitmap, null, Rect(50, 50, 500, 500), mPaint)
/**
 * @param x方向的错切量
 * @param y方向的错切量
 */
canvas?.skew(0.5f, 0f)
canvas?.drawBitmap(bitmap, null, Rect(50, 50, 500, 500), mPaint)
复制代码

Canvas还可以利用Matrix来完成变换,在后面再看看Matrix的作用

Canvas的裁剪功能

clipRect:矩形裁剪
/**
 * @param 裁剪的矩形
 */
canvas?.clipRect(Rect(150, 150, 400, 400))
canvas?.drawBitmap(bitmap, null, Rect(50, 50, 500, 500), mPaint)
复制代码

clipRect:路径裁剪
val path = Path()
path.addCircle(300f, 300f, 100f, Path.Direction.CW)
/**
 * @param 裁剪的路径
 */
canvas?.clipPath(path)
canvas?.drawBitmap(bitmap, null, Rect(50, 50, 500, 500), mPaint)
复制代码

Canvas的save、restore

save(): 用来保存Canvas的状态,save()方法之后的代码,可以调用Canvas的平移、放缩、旋转、裁剪等操作! restore():用来恢复Canvas之前保存的状态(可以想成是保存坐标轴的状态),防止save()方法代码之后对Canvas执行的操作,继续对后续的绘制会产生影响,通过该方法可以避免连带的影响

多次调用save来保存Canvas的状态,状态信息会以栈结构进行存储,每次调用restore都会恢复到上一存储状态,你可以使用restoreToCount来直接指定要恢复到哪一次状态

override fun onDraw(canvas: Canvas?) {
    canvas?.save()
    canvas?.rotate(30f)
    mPaint.color = Color.RED
    canvas?.drawLine(0f, 0f, 100f, 0f, mPaint)
    canvas?.save()
    mPaint.color = Color.GREEN
    canvas?.rotate(30f)
    canvas?.drawLine(0f, 0f, 100f, 0f, mPaint)
    canvas?.save()
    mPaint.color = Color.BLUE
    canvas?.rotate(30f)
    canvas?.drawLine(0f, 0f, 100f, 0f, mPaint)
    canvas?.restoreToCount(1)
    mPaint.color = Color.BLACK
    canvas?.drawLine(0f, 0f, 100f, 0f, mPaint)
}
复制代码

save还有一个重载的方法,需要传一个saveFlag,这些Flag标识的意义和使用范围如下:

我们上面说到的变换功能就是对canvas的matrix信息进行变换,裁剪功能就是对canvas的大小信息进行变换。 save的两个函数和saveLayer的两个函数不同之处在于saveLayer会新建一个layer(图层)

canvas?.drawColor(Color.RED)
/**
 * @param 图层信息存储的bitmap大小
 * @param 画笔
 * @param saveFlag
 */
canvas?.saveLayer(RectF(0f, 0f, 500f, 500f), mPaint, Canvas.ALL_SAVE_FLAG)
canvas?.rotate(30f)
mPaint.style = Paint.Style.FILL
mPaint.color = Color.GREEN
canvas?.drawRect(Rect(0, 0, 800, 800), mPaint)
canvas?.restore()
mPaint.style = Paint.Style.STROKE
canvas?.drawRect(Rect(0, 0, 800, 800), mPaint)
复制代码

以上就是canvas的一些主要的用法了