一、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)
}
}
運行結果如下: