1. 程式人生 > 資訊 >華為大佬解析開源鴻蒙 OpenHarmony 3.1 關鍵特性畫布,教你如何完成飛機大戰小遊戲

華為大佬解析開源鴻蒙 OpenHarmony 3.1 關鍵特性畫布,教你如何完成飛機大戰小遊戲

2 月 10 日訊息,華為技術有限公司的江英傑為大家揭曉了關於開源鴻蒙 OpenHarmony 3.1 Beta 版中的一個關鍵特性,也就是ArkUI 開發框架中的 canvas 畫布。

據介紹,canvas 是 ArkUI 開發框架裡的畫布元件,常用於自定義繪製圖形。因為其輕量、靈活、高效等優點,被廣泛應用於 UI 介面開發中。本期,我們將為大家介紹 ArkUI 開發框架中 canvas 元件的使用。

canvas 介紹

1.1 什麼是 canvas?

瞭解到,在 Web 瀏覽器中,canvas 是一個可自定義 width、height 的矩形畫布,畫布左上角為座標原點,以畫素為單位,水平向右為 x 軸,垂直向下為 y 軸,畫布內所有元素都基於原點進行定位。

如下圖所示,我們可以通過 <canvas> 標籤,建立了一個 width= 1500px,height=900px 的空白畫布,我們還需要“畫筆”才能繪製圖形。canvas 採用輕量的逐畫素渲染機制,以 JS 為“畫筆”直接控制畫布畫素,從而實現圖形繪製。

1.2 Canvas 的“畫筆”

canvas 本身雖不具備繪製能力,但是提供了獲取“畫筆”的方法。開發者可通過 getContext ('2d') 方法獲取 CanvasRenderingContext2D 物件完成 2D 影象繪製,或通過 getContext ('webgl') 方法獲取 WebGLRenderingContext 物件完成 3D 影象繪製。

目前,ArkUI 開發框架中的 WebGL1.0 及 WebGL2.0 標準 3D 圖形繪製能力正在完善中,所以本文將著重介紹 2D 影象的繪製。如下圖所示,是 CanvasRenderingContext2D 物件提供的部分 2D 影象繪製方法,豐富的繪製方法讓開發者能高效地繪製出矩形、文字、圖片等。

除此之外,開發者還可以通過獲取 OffscreenCanvasRenderingContext2D 物件進行離屏繪製,繪製方法同上。當繪製的圖形比較複雜時,頻繁地刪除與重繪會消耗很多效能。

這時,開發者可以根據自身的需求靈活選取離屏渲染的方式,首先通過建立 OffscreenCanvas 物件作為一個緩衝區,然後將內容繪製在 OffscreenCanvas 上,最後再將 OffscreenCanvas 繪製到主畫布上,以提高畫布效能,確保繪圖的質量。

canvas 基礎繪製方法

通過上節對 canvas 元件的基本介紹,相信大家對 canvas 元件已經有了一定的認識,下面我們將為大家實際演示 canvas 元件在 ArkUI 開發框架中的使用方法。ArkUI 開發框架參考了 Web 瀏覽器中 canvas 的設計,並在“類 Web 開發正規化”及“宣告式開發正規化”兩種開發正規化中進行提供,接下來我們將分別介紹這兩種開發正規化中 canvas 的繪製方法。

2.1 類 Web 開發正規化中 canvas 的繪製方法

類 Web 開發正規化,使用 HML 標籤檔案進行佈局搭建、CSS 檔案進行樣式描述,並通過 JS 語言進行邏輯處理。目前,JS 語言的 canvas 繪圖功能已經基本上完善,下面我們將通過兩個示例,展示基於 JS 語言的 canvas 元件基礎使用方法。

2.1.1 矩形填充

CanvasRenderingContext2D 物件提供了 fillRect (x, y, width, height) 方法,用於繪製一個填充的矩形。如下圖所示,在畫布內繪製了一個黑色的填充矩形,x 與 y 指定了在 canvas 畫布上所繪製的矩形的左上角(相對於原點)的座標,width 和 height 則設定了矩形的尺寸。

示例程式碼如下:

//建立一個width=1500px,height=900px的畫布<!--xxx.hml--><div><canvasref="canvas"style="width:1500px;height:900px;"></canvas></div>
//xxx.jsexportdefault{onShow(){constel=this.$refs.canvas;//獲取2D繪製物件constctx=el.getContext('2d');//設定填充為黑色ctx.fillStyle='#000000';//設定填充矩形的座標及尺寸ctx.fillRect(200,200,300,300);}}

2.1.2 縮放與陰影

CanvasRenderingContext2D 物件提供了 scale (x,y) 方法,引數 x 表示橫軸方向上縮放倍數,y 表示縱軸方向上縮放的倍數,值得注意的是縮放過程中定位也會被縮放。如下圖所示,是將上個示例中的填充矩形通過 scale (2,1.5) 縮放,並通過 shadowBlur 方法加上陰影后的效果。

示例程式碼如下:

//xxx.jsexportdefault{onShow(){constel=this.$refs.canvas;constctx=el.getContext('2d');//設定繪製陰影的模糊級別ctx.shadowBlur=80;ctx.shadowColor='rgb(0,0,0)';ctx.fillStyle='rgb(0,0,0)';//xScaleto200%,yScaleto150%ctx.scale(2,1.5);ctx.fillRect(200,200,300,300);}}

2.2 宣告式開發正規化中 canvas 的繪製方法

宣告式開發正規化,採用 TS 語言並進行宣告式 UI 語法擴充套件,從元件、動效和狀態管理三個維度提供了 UI 繪製能力,目前已經提供了 canvas 元件繪製能力,但功能仍在完善中。下面我們將通過兩個示例展示宣告式開發正規化中 canvas 元件的基礎使用方法。

2.2.1 圖片疊加

如下圖所示,是三張圖片疊加的效果,頂層的圖片覆蓋了底層的圖片。通過依次使用 drawImage (x,y, width, height) 方法設定圖片座標及尺寸,後面繪製的圖片自動覆蓋原來的影象,從而達到預期效果。

擴充套件的 TS 語言採用更接近自然語義的程式設計方式,讓開發者可以直觀地描述 UI 介面,示例程式碼如下:

@[email protected]IndexCanvas1{privatesettings:RenderingContextSettings=newRenderingContextSettings(true);//獲取繪圖物件privatectx:RenderingContext=newRenderingContext(this.settings);//列出所要用到的圖片privateimg:ImageBitmap=newImageBitmap("common/bg.jpg");build(){Column(){//建立canvasCanvas(this.ctx).width(1500).height(900).border({color:"blue",width:1,}).backgroundColor('#ffff00')//開始繪製.onReady(()=>{this.ctx.drawImage(this.img,400,200,540,300);this.ctx.drawImage(this.img,500,300,540,300);this.ctx.drawImage(this.img,600,400,540,300);})}.width('100%').height('100%')}}

2.2.2 點選建立線性漸變

如下圖所示,是一個線性漸變效果。基於 canvas 擴充套件了一個 Button 元件,通過點選“Click”按鈕,觸發 onClick () 方法,並通過呼叫 createLinearGradient () 方法,繪製出了一個線性漸變色。

示例程式碼如下:

@[email protected]GradientExample{privatesettings:RenderingContextSettings=newRenderingContextSettings(true);privatecontext:RenderingContext=newRenderingContext(this.settings);privategra:CanvasGradient=newCanvasGradient();build(){Column({space:5}){//建立一個畫布Canvas(this.context).width(1500).height(900).backgroundColor('#ffff00')Column(){//設定按鈕的樣式Button('Click').width(250).height(100).backgroundColor('#000000').onClick(()=>{//建立一個線性漸變色vargrad=this.context.createLinearGradient(600,200,400,750)grad.addColorStop(0.0,'red');grad.addColorStop(0.5,'white');grad.addColorStop(1.0,'green');this.context.fillStyle=grad;this.context.fillRect(400,200,550,550);})}.alignItems(HorizontalAlign.center)}}}

飛機大戰小遊戲繪製實踐

如下圖所示,是一款”飛機大戰”小遊戲,通過控制戰機的移動摧毀敵機。如何使用 ArkUI 開發框架提供的 canvas 元件輕鬆實現這個經典懷舊的小遊戲?實現思路及關鍵程式碼如下:

1. 首先列出遊戲所用到的圖片

privateimgList:Array<string>=["xx.png","xx.png"…];

2. 將圖片渲染到 canvas 畫布上

letimg:ImageBitmap=newImageBitmap("圖片路徑(如common/images)/"+this.imgList[陣列下標]);this.ctx.drawImage(img,150)

3. 繪製背景圖片和戰機向下移動的效果

this.ctx.drawImage(this.bg,0,this.bgY);this.ctx.drawImage(this.bg,0,this.bgY-480);this.bgY++==480&&(this.bgY=0);

4. 使用 Math.round 函式隨機獲取敵機圖片並渲染到畫布上,並且改變敵機 y 軸座標,使它向下運動。

Efight=Math.round(Math.random()*7);//前七張為敵機圖片。letimg:ImageBitmap=newImageBitmap("common/img"+this.imgList[Efight]);this.ctx.drawImage(img,0,this.Eheight+50);//渲染敵機

5. 在頁面每隔 120s 出現一排子彈,之後減小或增大(x,y)軸的座標達到子彈射出效果。

leti=0;setInterval(()=>{this.ctx.drawImage(this.bulImg1,image.x–10–(i*10),image.x+(i*10))this.ctx.drawImage(this.bulimg2,this.bulImg1,image.x–(i*10),iimage.x+(i*10))this.ctx.drawImage(this.bulimg3,image.x+10+(i*10),image.x+(i*10))i++;},120)

6. 使用 onTouch 方法獲取戰機移動位置,獲取拖動的座標後重新設定戰機的圖片座標,使戰機實現拖動效果。

.onTouch((event)=>{varoffsetX=event.localX||event.touches[0].localX;varoffsetY=event.localY||event.touches[0].localY;varw=this.heroImg[0].width,h=this.heroImg[0].height;varnx=offsetX-w/2,ny=offsetY-h/2;nx<20-w/2?nx=20-w/2:nx>(this.windowWidth-w/2-20)?nx=(this.windowWidth-w/2-20):0;ny<0?ny=0:ny>(this.windowHeight-h/2)?ny=(this.windowHeight–h/2):0;this.hero.x=nx;this.hero.y=ny;this.hero.count=2;

注:本示例引用了部分開源資源,感興趣的開發者可參考此開源資源,結合文中的實現思路補全程式碼。(https://github.com/ xs528 / game)

以上就是本期全部內容,期待廣大開發者能通過 canvas 元件繪製出精美的圖形,更多 canvas 元件的詳細使用方法,請參考文件進行學習:

https://developer.harmonyos.com/cn/docs/documentation/doc-references/js-components-canvas-canvas-0000000000621808