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