從微信小程序到鴻蒙JS開發-canvas&stack&2048
春節在家回看了張榮超老師的“從零開發鴻蒙小游戲APP“直播課(https://harmonyos.51cto.com/activity/17),聽完后在手機設備上完善了功能并實現了一個簡單的2048小游戲。這其中涉及到canvas和stack組件,在此做一些筆記。效果圖:
1、canvas組件
畫布組件,微信小程序也有,可以在其中動態繪制圖形和文字等。在2048游戲中,不同的數字對應的背景顏色都不同,如果使用動態樣式,判斷和渲染對性能的要求會很高。
- <canvas class="content" id="canvas" onswipe="swipeGrids"></canvas>
1.1 獲取繪圖上下文
組件給定id或者ref,即可在js中獲取組件繪圖上下文,通過獲取的CanvasRenderingContext2D對象進行繪圖。官方文檔提及獲取繪圖上下文的操作不支持在onInit和onReady中進行調用,經實驗如在onInit()中執行應用將白屏,在onReady()中執行畫布中的內容將無法被繪制,故需寫在onShow()中。
- // 繪圖對象
- var canvas;
- export default {
- data: {
- ...
- },
- onShow() {
- canvas = this.$element("canvas").getContext("2d");
- // 繪圖
- this.drawGrids();
- },
- ...
- }
對于會在多個方法之內使用的全局變量,可以寫在data中,也可以寫在export之外。對于無需在頁面中綁定的數據,寫在export外或許可以提高一點性能。
1.2 監聽滑動事件
在畫布中滑動的事件綁定是通過onswipe屬性,這個在官方文檔中沒有說明,但是IDE是有提示的。對于方法的入參,打日志后看出結構如下:
event.direction有四種取值:up/down/left/right,可用于判斷滑動方向。
1.3 繪制矩形
- canvas.fillStyle = "#ffffff";
獲取繪圖上下文對象后,將其fillStyle屬性設置為十六進制顏色即可設置本次繪圖的顏色。也可使用createLinearGradient()給定漸變色,createPattern()創建填充模版。
- canvas.fillRect(leftTopX, leftTopY, gridWidth, gridWidth);
fillRect()方法用于繪制矩形,四個參數分別為左上角X坐標,左上角Y坐標,寬度,高度。
1.4 繪制文字
- canvas.font = "70px HYQiHei-65S";
- canvas.fillStyle = gridTxColors[gridVal];
font屬性指定文字的大小和字體,fillStyle指定文字的顏色。
- canvas.fillText(text, leftBottomX, leftBottomY);
fillText()方法用于繪制文字,三個參數分別為文字內容,左下角X坐標,左下角Y坐標。這里后兩個參數是左下角,和微信小程序以及剛才提到的fillRect()不同。
繪制2048格子及文字的方法:
- // 繪制格子 grids:存儲數字的二維數組; gridBgColors:存儲格子背景色的對象; gridTxColors:存儲文字顏色的對象
- drawGrids() {
- for (let r = 0; r < 4; r++) {
- for (let c = 0; c < 4; c++) {
- let gridVal = grids[r][c].toString();
- // 繪制背景
- canvas.fillStyle = gridBgColors[gridVal];
- let leftTopX = c * (gridWidth + gridMargin) + gridMargin;
- let leftTopY = r * (gridWidth + gridMargin) + gridMargin;
- // 左上角x 左上角y 寬度 高度
- canvas.fillRect(leftTopX, leftTopY, gridWidth, gridWidth);
- // 繪制文字
- canvas.font = "70px HYQiHei-65S";
- if (gridVal != "0") {
- if (gridVal == "2" || gridVal == "4") {
- canvas.fillStyle = gridTxColors[gridVal];
- } else {
- canvas.fillStyle = gridTxColors["others"];
- }
- let offsetX = (4 - gridVal.length) * (gridWidth / 8);
- let offsetY = (gridWidth - fontSize) / 2;
- // 文字 左下角x 左下角y
- canvas.fillText(gridVal, leftTopX + offsetX, leftTopY + offsetY + fontSize - 5);
- }
- }
- }
- },
每次數字改變后,調用以上方法即可將2048的效果繪制出。
2、stack組件
這個組件很有意思,在stack中的子元素會順序入棧,實現堆疊效果。一般都是通過z-index的樣式實現,而鴻蒙這里的實現將數據結構的棧與頁面層級相結合,非常巧妙。
在游戲結束時,提示文字將覆蓋格子區域:
- <stack class="content">
- <canvas class="content" id="canvas" onswipe="swipeGrids"></canvas>
- <div show="{{ isEnd }}">
- <text>
- 游戲結束
- </text>
- </div>
- </stack>
事實上,鴻蒙js組件是不支持z-index樣式的。