网易首页 > 网易号 > 正文 申请入驻

开源鸿蒙 OpenHarmony 3.1画布解析,教你如何完成飞机大战小游戏

0
分享至

IT之家 2 月 10 日消息,华为技术有限公司的江英杰为大家揭晓了关于开源鸿蒙 OpenHarmony 3.1 Beta 版中的一个关键特性,也就是ArkUI 开发框架中的 canvas 画布。

据介绍,canvas 是 ArkUI 开发框架里的画布组件,常用于自定义绘制图形。因为其轻量、灵活、高效等优点,被广泛应用于 UI 界面开发中。本期,我们将为大家介绍 ArkUI 开发框架中 canvas 组件的使用。

canvas 介绍

1.1 什么是 canvas?

IT之家了解到,在 Web 浏览器中,canvas 是一个可自定义 width、height 的矩形画布,画布左上角为坐标原点,以像素为单位,水平向右为 x 轴,垂直向下为 y 轴,画布内所有元素都基于原点进行定位。

如下图所示,我们可以通过 标签,创建了一个 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.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 界面,示例代码如下:

@Entry@ComponentstructIndexCanvas1{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 () 方法,绘制出了一个线性渐变色。

示例代码如下:

@Entry@ComponentstructGradientExample{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=["xx.png","xx.png"…];

2. 将图片渲染到 canvas 画布上

letimg:ImageBitmap=newImageBitmap("图片路径(如common/images)/"+this.imgList[数组下标]);this.ctx.drawImage(img,150/*x坐标*/,150/*y坐标*/,600/*宽*/,600/*高*/)

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

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
可笑!中方军演刚结束,菲律宾在仙宾礁升国旗!其实只是自娱自乐

可笑!中方军演刚结束,菲律宾在仙宾礁升国旗!其实只是自娱自乐

梦涵说体育
2024-06-17 14:14:15
中科院已发表颠覆性研究:尼古丁可延缓衰老!吸烟或是长寿密码?

中科院已发表颠覆性研究:尼古丁可延缓衰老!吸烟或是长寿密码?

蜉蝣说
2024-06-15 21:38:43
武统、和统都没希望了?台湾军事专家:中国大陆已经找到第三条路

武统、和统都没希望了?台湾军事专家:中国大陆已经找到第三条路

车马点兵V
2024-06-15 11:04:03
当年轻人不再缴纳社保:一场静悄悄的危机

当年轻人不再缴纳社保:一场静悄悄的危机

经济学教授V
2024-06-17 07:04:56
不会出口欧美!拜登做梦也没想到,中国出手会这么狠

不会出口欧美!拜登做梦也没想到,中国出手会这么狠

科技龙
2024-06-12 10:23:18
推荐2本很有特点的完结小说,一本架空历史,一本奇幻类虚拟网游

推荐2本很有特点的完结小说,一本架空历史,一本奇幻类虚拟网游

阿晖推书
2024-06-16 12:04:37
有点名气就把自己当巨星!对着央视耍大牌、顶嘴还狡辩,可真行

有点名气就把自己当巨星!对着央视耍大牌、顶嘴还狡辩,可真行

娱乐圈笔娱君
2024-06-15 18:12:03
赛过西施类型美女(118)

赛过西施类型美女(118)

娱记掌门
2024-06-11 17:57:52
被中国人耍了?美国联邦航空局调查有问题的钛如何进入波音和空客

被中国人耍了?美国联邦航空局调查有问题的钛如何进入波音和空客

嘿哥哥科技
2024-06-15 22:11:11
凯特王妃正式复出!这四个核心问题,你可能还不知道

凯特王妃正式复出!这四个核心问题,你可能还不知道

农村教育光哥
2024-06-16 13:54:16
理想汽车车友汕头活动多车追尾 组织者:突遭大雨,车距较近,致5车追尾

理想汽车车友汕头活动多车追尾 组织者:突遭大雨,车距较近,致5车追尾

红星新闻
2024-06-16 19:16:10
总决赛G5票价出炉!均价2213美元创纪录 38分惨败后大赚一笔

总决赛G5票价出炉!均价2213美元创纪录 38分惨败后大赚一笔

罗说NBA
2024-06-16 05:56:09
医科大教师因抢救患儿上课迟到受处分?校方称正核实,学生称OA系统曾发处分通报

医科大教师因抢救患儿上课迟到受处分?校方称正核实,学生称OA系统曾发处分通报

上游新闻
2024-06-16 13:32:18
银行这次被坑惨了!经理勾结员工窃取储户230万,被禁止终身从业

银行这次被坑惨了!经理勾结员工窃取储户230万,被禁止终身从业

刚哥说法365
2024-06-16 14:02:48
感谢张立平老人,让人们看到了国人心中的道义依旧在

感谢张立平老人,让人们看到了国人心中的道义依旧在

清晖有墨
2024-06-17 13:06:13
姜萍的成功却成了一场闹剧,背后黑手究竟何为?

姜萍的成功却成了一场闹剧,背后黑手究竟何为?

娱乐洞察点点
2024-06-16 22:09:31
申台龙:当八万人在体育场内高呼我的名字时,我被震撼到了

申台龙:当八万人在体育场内高呼我的名字时,我被震撼到了

懂球帝
2024-06-17 10:58:14
总决赛赛程出炉!冤家路窄:中国女排又遇日本队 复仇战 万众瞩目

总决赛赛程出炉!冤家路窄:中国女排又遇日本队 复仇战 万众瞩目

草根体育
2024-06-17 00:09:07
《玫瑰的故事》播出一半后才发现,刘亦菲根本不是天选的“玫瑰”

《玫瑰的故事》播出一半后才发现,刘亦菲根本不是天选的“玫瑰”

兰子记
2024-06-15 20:36:41
四巨头解体!再见,快船!你好,76人

四巨头解体!再见,快船!你好,76人

篮球教学论坛
2024-06-17 00:08:51
2024-06-17 15:24:49
IT之家
IT之家
爱科技,爱这里 - 前沿科技人气平台
233560文章数 604995关注度
往期回顾 全部

科技要闻

为什么你的iPhone,肯定用不上"苹果AI"?

头条要闻

媒体:和平峰会或让泽连斯基落寞 美带头早退德日跟上

头条要闻

媒体:和平峰会或让泽连斯基落寞 美带头早退德日跟上

体育要闻

豪华阵容,原始战术 英格兰10亿天团就这?

娱乐要闻

上影节红毯:倪妮好松弛,娜扎吸睛

财经要闻

省市级税务人士:目前没有全国性查税

汽车要闻

传奇新篇章 全新一代大众迈腾来了

态度原创

数码
健康
亲子
艺术
军事航空

数码要闻

Powkiddy V10 复古掌机发布:3.5 英寸全贴合 IPS 屏、四核 A35

晚餐不吃or吃七分饱,哪种更减肥?

亲子要闻

“隔着屏幕都能闻到她的奶香味了”

艺术要闻

穿越时空的艺术:《马可·波罗》AI沉浸影片探索人类文明

军事要闻

13国未签署瑞士乌克兰和平峰会联合声明

无障碍浏览 进入关怀版