画布 - Canvas

# 画布 canvas提供了使用画布进行2D画图的支持,可用于简单的小游戏开发或者图片编辑。使用canvas可以轻松地在一张图片或一个界面上绘制各种线与图形。 > **注意!** Canvas模块本质上是将 [Android Canvas](https://developer.android.google.cn/reference/android/graphics/Canvas) 进行包装后的结果。本模块的部分用法和文档暂时缺失,但可以在 Android 文档中找到。请参阅 [Android Canvas](https://developer.android.google.cn/reference/android/graphics/Canvas)、[Android Paint](https://developer.android.google.cn/reference/android/graphics/Paint) 与 [Android Path](https://developer.android.google.cn/reference/android/graphics/Path) 了解更多细节。 canvas的坐标系为平面直角坐标系,以控件左上角为原点,控件上边沿为x轴正方向,控件左边沿为y轴正方向。例如分辨率为1920*1080的屏幕上,canvas控件覆盖全屏,画一条从屏幕左上角到屏幕右下角的线段为: ```javascript canvas.drawLine(0, 0, 1080, 1920, paint); ``` canvas的绘制依赖于画笔Paint, 通过设置画笔的粗细、颜色、填充等可以改变绘制出来的图形。例如绘制一个红色实心正方形为: ```javascript let paint = new Paint(); // 设置画笔为填充,则绘制出来的图形都是实心的 paint.setStyle(Paint.STYLE.FILL); // 设置画笔颜色为红色 paint.setColor(colors.RED); // 绘制一个从坐标(0, 0)到坐标(100, 100)的正方形 canvas.drawRect(0, 0, 100, 100, paint); ``` 如果要绘制正方形的边框,则通过设置画笔的Style来实现: ```javascript let paint = new Paint(); // 设置画笔为描边,则绘制出来的图形都是轮廓 paint.setStyle(Paint.STYLE.STROKE); // 设置画笔颜色为红色 paint.setColor(colors.RED); // 绘制一个从坐标(0, 0)到坐标(100, 100)的正方形 canvas.drawRect(0, 0, 100, 100, paint); ``` 结合画笔,canvas可以绘制基本图形、图片等。 ## 常用方法索引 绘制颜色: - 根据R、G、B分量绘制颜色:[canvas.drawRGB(r, g, b)](#canvasdrawrgbr-g-b) - 根据A、R、G、B分量绘制颜色:[canvas.drawARGB(r, g, b)](#canvasdrawargba-r-g-b) - 根据颜色值绘制颜色:[canvas.drawColor(color)](#canvasdrawcolorcolor) - 根据颜色值与混合模式绘制颜色:[canvas.drawColor(color, mode)](#canvasdrawcolorcolor-mode) 绘制画笔: - [canvas.drawPaint(paint)](#canvasdrawpaintpaint) 绘制几何图形: - 绘制一个点:[canvas.drawPoint(x, y, paint)](#canvasdrawpointx-y-paint) - 绘制多个点:[canvas.drawPoints(pts, paint)](#canvasdrawpointspts-paint) - 绘制一条线:[canvas.drawLine(startX, startY, stopX, stopY, paint)](#canvasdrawlinestartx-starty-stopx-stopy-paint) - 绘制多条线:[canvas.drawLines(pts, paint)](#canvasdrawlinespts-paint) - 绘制矩形:[canvas.drawRect(r, paint)](#canvasdrawrectr-paint) - 绘制椭圆:[canvas.drawOval(oval, paint)](#canvasdrawovaloval-paint) - 绘制圆:[canvas.drawCircle(cx, cy, radius, paint)](#canvasdrawcirclecx-cy-radius-paint) - 绘制弧:[canvas.drawArc(oval, startAngle, sweepAngle, useCenter, paint)](#canvasdrawarcoval-startangle-sweepangle-usecenter-paint) - 绘制圆角矩形:[canvas.drawRoundRect(rect, rx, ry, paint)](#canvasdrawroundrectrect-rx-ry-paint) - 绘制路径:[canvas.drawPath(path, paint)](#canvasdrawpathpath-paint) 绘制文字: - 沿直线绘制文字:[canvas.drawText(text, x, y, paint)](#canvasdrawtexttext-x-y-paint) - 沿路径绘制文字:[canvas.drawTextOnPath(text, path, hOffset, vOffset, paint)](#canvasdrawtextonpathtext-path-hoffset-voffset-paint) 绘制图片: - 绘制位图:[canvas.drawBitmap(bitmap, left, top, paint)](#canvasdrawbitmapbitmap-left-top-paint) - 绘制图章:[canvas.drawPicture(picture)](#canvasdrawpicturepicture) 获取画布大小: - 获取宽度:[canvas.getWidth()](#canvasgetwidth) - 获取高度:[canvas.getHeight()](#canvasgetheight) 矩阵变换: - 平移:[canvas.translate(dx, dy)](#canvastranslatedx-dy) - 缩放:[canvas.scale(sx, sy[, px, py])](#canvasscalesx-sy-px-py) - 旋转:[canvas.rotate(degrees[, px, py])](#canvasrotatedegrees-px-py) - 切变变换:[canvas.skew(sx, sy)](#canvasskewsx-sy) ## canvas.getWidth() * 返回 {number} 返回画布当前图层的宽度。 ## canvas.getHeight() * 返回 {number} 返回画布当前图层的高度。 ## canvas.drawRGB(r, g, b) * `r` {number} 红色通道值 * `g` {number} 绿色通道值 * `b` {number} 蓝色通道值 将整个可绘制区域填充为r、g、b指定的颜色。相当于 `canvas.drawColor(colors.rgb(r, g, b))`。 ## canvas.drawARGB(a, r, g, b) * `a` {number} 透明通道值 * `r` {number} 红色通道值 * `g` {number} 绿色通道值 * `b` {number} 蓝色通道值 将整个可绘制区域填充为a、r、g、b指定的颜色。相当于 `canvas.drawColor(colors.argb(a, r, g, b))`。 ## canvas.drawColor(color) * `color` {number} 颜色值 将整个可绘制区域填充为color指定的颜色。 ## canvas.drawColor(color, mode) * `color` {number} 颜色值 * `mode` {PorterDuff.Mode} 混合模式 将整个可绘制区域按mode指定的混合模式填充为color指定的颜色。 ## canvas.drawPaint(paint) * `paint` {Paint} 画笔 将整个可绘制区域用paint指定的画笔填充。相当于绘制一个无限大的矩形,但是更快。通过该方法可以绘制一个指定的着色器的图案。 ## canvas.drawPoint(x, y, paint) * `x` {number} x坐标 * `y` {number} y坐标 * `paint` {Paint} 画笔 在可绘制区域绘制由坐标(x, y)指定的点。 点的形状由画笔的线帽决定(参见paint.setStrokeCap(cap))。 点的大小由画笔的宽度决定(参见paint.setStrokeWidth(width))。 > 如果画笔宽度为0,则也会绘制1个像素(若抗锯齿启用则绘制至多4个像素)。 相当于 `canvas.drawPoints([x, y], paint)`。 ## canvas.drawPoints(pts, paint) * `pts` {Array} 点坐标数组 [x0, y0, x1, y1, x2, y2, ...] * `paint` {Paint} 画笔 在可绘制区域绘制由坐标数组指定的多个点。 ## canvas.drawLine(startX, startY, stopX, stopY, paint) * `startX` {number} 起点x坐标 * `startY` {number} 起点y坐标 * `endX` {number} 终点x坐标 * `endY` {number} 终点y坐标 * `paint` {Paint} 画笔 在可绘制区域绘制由起点坐标(startX, startY)和终点坐标(endX, endY)指定的线。 绘制时会忽略画笔的样式(Style)。也就是说,即使样式设为“仅填充(FILL)”也会绘制。 退化为点的线(长度为0)不会被绘制。 ## canvas.drawLines(pts, paint) * `pts` {Array} 点坐标数组 [x0, y0, x1, y1, x2, y2, ...] * `paint` {Paint} 画笔 在可绘制区域绘制由坐标数组指定的点两两连成的一系列线。 每条线需要点坐标数组中的四个连续的值,因此要绘制一条线,数组必须至少包含四个值。 相当于 `canvas.drawLine(pts[0], pts[1], pts[2], pts[3], paint)` 然后 `canvas.drawLine(pts[4], pts[5], pts[6], pts[7], paint)`,之后以此类推。 绘制时会忽略画笔的样式(Style)。也就是说,即使样式设为“仅填充(FILL)”也会绘制。 ## canvas.drawRect(r, paint) * `r` {Rect|RectF} 矩形边界 * `paint` {Paint} 画笔 在可绘制区域绘制由矩形边界r指定的矩形。 绘制时画笔的样式(Style)决定了是否绘制矩形界线和填充矩形。 相当于 `canvas.drawRect(r.left, r.top, r.right, r.bottom, paint)`。 ## canvas.drawRect(left, top, right, bottom, paint) * `left` {number} 矩形左边界x坐标 * `top` {number} 矩形上边界y坐标 * `right` {number} 矩形右边界x坐标 * `bottom` {number} 矩形下边界y坐标 * `paint` {Paint} 画笔 在可绘制区域绘制由矩形边界(left, top) - (right, bottom)指定的矩形。 绘制时画笔的样式(Style)决定了是否绘制矩形界线和填充矩形。 ## canvas.drawOval(oval, paint) * `oval` {RectF} 椭圆的外接矩形的边界 * `paint` {Paint} 画笔 在可绘制区域绘制由矩形边界oval指定的椭圆。 绘制时画笔的样式(Style)决定了是否绘制椭圆界线和填充椭圆。 相当于 `canvas.drawOval(oval.left, oval.top, oval.right, oval.bottom, paint)`。 ## canvas.drawOval(left, top, right, bottom, paint) * `left` {number} 椭圆外接矩形的左边界x坐标 * `top` {number} 椭圆外接矩形的上边界y坐标 * `right` {number} 椭圆外接矩形的右边界x坐标 * `bottom` {number} 椭圆外接矩形的下边界y坐标 * `paint` {Paint} 画笔 在可绘制区域绘制由矩形边界(left, top) - (right, bottom)指定的椭圆。 绘制时画笔的样式(Style)决定了是否绘制椭圆界线和填充椭圆。 ## canvas.drawCircle(cx, cy, radius, paint) * `cx` {number} 圆心的x坐标 * `cy` {number} 圆心的y坐标 * `radius` {number} 圆的半径 * `paint` {Paint} 画笔 在可绘制区域绘制由圆心(cx, cy)与半径radius指定的圆。如果半径小于等于0则不会绘制。 绘制时画笔的样式(Style)决定了是否绘制圆的界线和填充圆。 ## canvas.drawArc(oval, startAngle, sweepAngle, useCenter, paint) * `oval` {RectF} 圆弧对应的椭圆外接矩形的边界 * `startAngle` {number} 圆弧的起始角(以角度计算) * `sweepAngle` {number} 圆弧所对的圆心角(顺时针方向,以角度计算) * `useCenter` {boolean} 绘制路径时是否连接圆弧对应的椭圆圆心 * `paint` {Paint} 画笔 在可绘制区域绘制指定的圆弧。 这一圆弧是由矩形边界oval指定的椭圆的一部分,起始于startAngle指定的角度,并以顺时针方向扫过sweepAngle指定的角度。 如果起始角startAngle为负数或大于等于360,则绘制时起始角将对360取模。 圆弧是沿顺时针方向绘制的。起始角0°相当于从直角坐标系的0°开始绘制(即从3点钟方向沿顺时针方向绘制)。 如果圆心角sweepAngle大于等于360,则此函数将绘制一个完整的椭圆。 注意,这与path.arcTo方法不同,path.arcTo会将圆心角对360取模。 如果圆心角为负数则会将圆心角对360取模。 如果指定useCenter为true,在描边和填充时将会连接圆弧对应的椭圆圆心,最终将绘制出一个扇形。 相当于 `canvas.drawArc(oval.left, oval.top, oval.right, oval.bottom, startAngle, sweepAngle, useCenter, paint)`。 ## canvas.drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint) * `left` {number} 椭圆外接矩形的左边界x坐标 * `top` {number} 椭圆外接矩形的上边界y坐标 * `right` {number} 椭圆外接矩形的右边界x坐标 * `bottom` {number} 椭圆外接矩形的下边界y坐标 * `startAngle` {number} 圆弧的起始角(以角度计算) * `sweepAngle` {number} 圆弧所对的圆心角(顺时针方向,以角度计算) * `useCenter` {boolean} 绘制路径时是否连接圆弧对应的椭圆圆心 * `paint` {Paint} 画笔 在可绘制区域绘制指定的圆弧。这一圆弧是由矩形边界(left, top) - (right, bottom)指定的椭圆的一部分,其余参数请参见 [canvas.drawArc(oval, startAngle, sweepAngle, useCenter, paint)](#canvasdrawarcoval-startangle-sweepangle-usecenter-paint)。 ## canvas.drawRoundRect(rect, rx, ry, paint) * `rect` {RectF} 矩形边界 * `rx` {number} 圆角在x轴上的半径 * `ry` {number} 圆角在y轴上的半径 * `paint` {Paint} 画笔 在可绘制区域绘制由矩形边界rect、圆角半径rx、ry指定的圆角矩形。 绘制时画笔的样式(Style)决定了是否绘制圆角矩形界线和填充圆角矩形。 相当于 `canvas.drawRoundRect(rect.left, rect.top, rect.right, rect.bottom, rx, ry, paint)`。 ## canvas.drawRoundRect(left, top, right, bottom, rx, ry, paint) * `left` {number} 圆角矩形左边界x坐标 * `top` {number} 圆角矩形上边界y坐标 * `right` {number} 圆角矩形右边界x坐标 * `bottom` {number} 圆角矩形下边界y坐标 * `rx` {number} 圆角在x轴上的半径 * `ry` {number} 圆角在y轴上的半径 * `paint` {Paint} 画笔 在可绘制区域绘制由矩形边界(left, top) - (right - bottom)、圆角半径rx、ry指定的圆角矩形。 绘制时画笔的样式(Style)决定了是否绘制圆角矩形界线和填充圆角矩形。 ## canvas.drawPath(path, paint) * `path` {Path} 路径 * `paint` {Paint} 画笔 在可绘制区域绘制指定的路径。 绘制时画笔的样式(Style)决定了是否描边路径和填充路径。 ## canvas.drawBitmap(bitmap, left, top, paint) * `bitmap` {Bitmap} 位图 * `left` {number} x坐标 * `top` {number} y坐标 * `paint` {Paint} 画笔 在可绘制区域绘制指定的位图,使它的左上角位于(left, top)指定的坐标,并应用画布的变换矩阵。 > **注意!** 如果画笔指定了遮罩过滤器并且该过滤器范围比位图大(超出位图的长/宽)(如 BlurMaskFilter),位图将会像被应用了CLAMP铺展模式的着色器一样绘制。因此超出位图原始范围的颜色将会重复使用边缘的颜色。 如果位图bitmap与画布canvas的密度不同,在绘制时位图将会被缩放至与画布相同密度再绘制。 ## canvas.drawPicture(picture) * `picture` {Picture} 图章 保存画布的变换矩阵与可绘制区域范围,在可绘制区域绘制指定的图章,随后恢复画布的变换矩阵与可绘制区域范围。 该过程与 `picture.draw(canvas)` 不同,因为后者不会进行保存与恢复的操作。 > **注意!**绘制图章将会强制图章退出录制模式(即调用 `picture.endRecording()`)以准备之后的绘制。 ## canvas.drawText(text, x, y, paint) * `text` {string} 文字 * `x` {number} x坐标 * `y` {number} y坐标 * `paint` {Paint} 画笔 在可绘制区域绘制指定的文字,使文字的原点位于(x, y)。文字的起始位置取决于paint的对齐选项。 文字的样式取决于paint的相关设置。 ## canvas.drawTextOnPath(text, path, hOffset, vOffset, paint) * `text` {string} 文字 * `path` {Path} 路径 * `hOffset` {number} 在与路径平行方向的偏移,取正为沿路径方向平移 * `vOffset` {number} 在与路径垂直方向的偏移,取正为向文字的下方平移 * `paint` {Paint} 画笔 在可绘制区域沿着指定的路径绘制指定的文字。文字的起始位置取决于paint的对齐选项。 文字的样式取决于paint的相关设置。 ## canvas.translate(dx, dy) * `dx` {number} 向x轴正方向平移的距离,负数表示反方向平移 * `dy` {number} 向y轴正方向平移的距离,负数表示反方向平移 将当前的变换矩阵右乘指定的平移变换矩阵。相当于将坐标系平移指定距离。 ## canvas.scale(sx, sy[, px, py]) * `sx` {number} 在x轴上缩放的倍数,负数表示沿x轴翻转 * `sy` {number} 在y轴上缩放的倍数,负数表示沿y轴翻转 * `px` {number} 缩放中心的x坐标,默认为0 * `py` {number} 缩放中心的y坐标,默认为0 将当前的变换矩阵右乘指定的缩放变换矩阵。相当于以(px, py)为中心将坐标系缩放指定的倍数。 倍数大于 1 表示放大,小于 1 表示缩小。 ## canvas.rotate(degrees[, px, py]) * `degrees` {number} 旋转的角度(以角度计算) * `px` {number} 旋转中心的x坐标,默认为0 * `py` {number} 旋转中心的y坐标,默认为0 将当前的变换矩阵右乘指定的旋转变换矩阵。相当于以(px, py)为中心将坐标系旋转指定的角度。 ## canvas.skew(sx, sy) * `sx` {number} x轴方向的切变系数 * `sy` {number} y轴方向的切变系数 将当前的变换矩阵右乘指定的切变变换矩阵。 # 画笔 # 变换矩阵 # 路径 # Porter-Duff模式与混合模式 # 图章 # 着色器 # 遮罩过滤器 # 颜色过滤器 # 路径特效 # 区域 # 字体 # 位图与图像解码器 # .9图