【QML 画布Canvas】2D绘图(上)
一、Canvas 介绍
要绘图先要有纸,即画布也。Qt5 中引进了画布元素 Canvas,该类型继承自Item,允许脚本绘制。Canvas 提供了一个依赖于分辨率的位图画布,能够使用JavaScript绘制直线和曲线、简单和复杂的图形、图像等等,还可以添加文本、颜色、渐变和图案以及像素的操作。
Canvas 元素基于 HTML5 的 canvas 元素,其基本思想是提供一个用于渲染路径的 Context2D 对象,这个对象就是在 Canvas 上进行绘制的画笔,提供必要的绘图函数,包括画线、填充、渐变、文字、路径的创建等,更多细节类容可在帮助文档中搜索 Canvas 关键字了解。
1.1 Canvas 如何使用
使用 Canvas 对象创建了一个宽 320,高 240 的绘制区域,即画布,代码如下:
Canvas {
width: 320
height: 240
}
1.2 基本属性介绍
available:该属性用于设置 Canvs 是否可用,只有为 true 时后续的操作才有效;
canvasSize:设置canvas的逻辑大小,逻辑大小也是也是可以进行绘制的区域大小,默认情况下与当前画布中已有项目大小一致,虽然可以设置,但是只有出现在视口的元素时才会被Canvas渲染引擎绘制;
renderStrategy:用于设置渲染策略
renderTarget:用于设置canvas的渲染目标,目前支持以下两种:
- Canvas.Image - render to an in memory image buffer.
- Canvas.FramebufferObject - render to an OpenGL frame buffer
二、绘制操作
Context2D 类型提供了两种绘制方式:填充或描边:
- 填充会将一个区域的内部使用某种方式进行覆盖,使用 fillStyle() 函数。
- 描边则使用线条将一个区域的边框勾画出来,使用 strokeStyle() 函数。
Context2D 提供了一个经典的二维笛卡尔坐标,默认情况下是与窗口坐标系统相同,原点 (0 ,0) 位于左上角,x 轴正方向向右,y 轴正方向向下,坐标如下:
然而 Canvas 的坐标系并不是固定的,我们可以对坐标系统进行平移、缩放及旋转等,在后面我们会专门讲解。
2.1 绘制矩形
Canvas 没有提供过多的基本图元的绘制 API 仅有矩形的绘制,这是因为矩形相比其他图元更为常用,并且矩形的填充可以直接作为 Canvas 的背景填充,同时在实现动画等效果时,由于效率问题,通常还要清除某一矩形区域。
针对矩形的绘制,Canvas 提供了三种方法:
- fillRect函数以填充方式绘制矩形;
- strokeRect函数以描边方式绘制矩形;
- clearRect函数清除矩形区域。
示例如下:
import QtQuick 2.9
// 画布
Canvas {
width: 400
height: 240
onPaint: {
var ctx = getContext("2d")
ctx.lineWidth = 2 // 画笔宽度
ctx.strokeStyle = "red" // 画笔颜色(边框颜色)
ctx.fillStyle = "blue" // 画刷颜色
ctx.beginPath()
ctx.rect(100, 80, 120, 80) // 绘制矩形
ctx.fill()
ctx.stroke()
}
}
这个例子产生了一个在坐标(100, 80),宽度为 120,高宽为 80 的填充矩形框,并且使用了画笔来修饰边界。执行 “qmlscenedraw_rect.qml” 命令,效果如下图所示。
这个示例展示了使用 Canvas 和 Context2D 绘图的一般步骤:
(1)定义一个 Canvas 对象,设置 width、height;
(2)定义 onPaint 信号处理器;
(3)获取 Context2D 对象;
(4)实际的绘图操作。
paint 是 Canvas 的信号,当需要绘图(更新)时会触发,开发者通过实现名为 onPaint 的信号处理器来响应 paint 信号,在信号处理器内进行绘图。
另外还有一种使用 Context2D 对象的方式:设置 Canvas 对象的 contextType 属性(取值为 "2d”)后,context 属性就会保存一个可用的 Context2D 对象。
2.2 绘制路径
Canvas 提供了简单的矩形绘制 API,但是实际应用中还有很多复杂图形,在 Canvas 中所有的图形都以路径为基础,我们以 beginPath() 和 closePath() 一组函数去通知 Context2D 开始绘制路径和结束绘制路径,一边形成一个环路,closePath 也可有系统自动调用。
-
lineTo(x,y):该函数将提供当前坐标到x,y之间的一条直线;
-
object arc(real x, real y, real radius, real startAngle, real endAngle, bool anticlockwise):添加一段圆弧
下面是一段示例:
import QtQuick 2.9
Canvas {
width: 240; height: 160
onPaint: {
var ctx = getContext("2d");
ctx.lineWidth = 2
ctx.beginPath()
ctx.moveTo(0, 60)
ctx.lineTo(240, 60)
ctx.stroke()
ctx.beginPath()
ctx.moveTo(30, 60)
ctx.arc(30, 60, 20, 0, -Math.PI / 2, true)
ctx.stroke()
ctx.beginPath()
ctx.moveTo(90, 60)
ctx.arc(90, 60, 20, 0, Math.PI, true)
ctx.stroke()
ctx.beginPath()
ctx.moveTo(150, 60)
ctx.arc(150, 60, 20, 0, -3 * Math.PI / 2, true)
ctx.stroke()
ctx.beginPath()
ctx.moveTo(210, 60)
ctx.arc(210, 60, 20, 0, Math.PI * 2, true)
ctx.stroke()
}
}
运行效果如下:
2.3 绘制文本
与矩形类似,Canvas 也提供了两种绘制文本的方法:
- 填充:fillText(text,x,y) 以填充方式绘制文本 text,其中文本的左上角位于 (x,y);
- 描边:strokeText(text,x,y) 以描边方式绘制文本text,其中文本的左上角位于(x,y);
下面看一个示例:
import QtQuick 2.9
Canvas {
width: 300; height: 300
onPaint: {
var ctx = getContext("2d");
ctx.fillStyle = "green"
ctx.strokeStyle = "blue"
ctx.lineWidth = 2
ctx.font = "bold 50px Arial"
var text = "qter.org";
context.fillText(text, 10, 80)
context.strokeText(text, 10, 150)
}
}
运行结果如下: