版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、梦中的婚礼于鹏飞技术解析主题图形渲染引擎的设计与实现 华为分享与原子化服务 项目设计理念与技术解析JavaScript与Java相互通信Web前端从业者如何学习鸿蒙应用设计理念与核心功能应用背景2D版换装秀!结合疫情当下的时代背景,弥补新人无法蜜月旅行的遗憾,软件模拟梦中婚礼的盛况。这是一款传统Web应用,在鸿蒙系统分布式能力的加持下,迸发出新的活力。核心功能 单机模式单机模式核心功能:切换场景:选择舞台场景,切换场景主题。创建精灵:创建精灵元素:人物、装饰、宠物等。拖拽精灵:拖拽调整精灵摆放位置。缩放精灵:通过缩放改变精灵尺寸。删除精灵:从场景中移除不需要的精灵。局部替换:新郎/新娘可替换发
2、型与服装。旋转精灵:精灵主体旋转,局部精灵同步操作。核心功能 多端协同多端协同操作,便捷又高效!主设备将应用的部分能力迁移到另一台设备中(控制面板)。主设备:场景铺满,最大化可视区域。从设备:作为控制面板,负责选择精灵。核心功能 快捷分享华为分享,实现独立设备之间的应用共享!通过华为的近场通讯技术,将原子化服务快捷的分享给其他设备,打破传统束缚,分享更方便,服务更贴近。蓝牙+WLAN技术解析技术解析Canvas画布二次编辑选中画布中的某个精灵平移、缩放、旋转精灵替换精灵局部内容精灵与其组成部分同比例缩放系统分布式能力多设备协同(控制面板迁移)从设备控制主设备创建精灵技术解析鸿蒙系统分布式渲染引
3、擎业务功能多端协同跨端迁移为什么要自己做渲染引擎?1、目前无鸿蒙专用Canvas图形引擎。2、Web端图形引擎体积大,存在DOM api与平台兼容性代码,不易抽离逻辑(Pixi6.2.2 500KB)。3、极致压缩应用体积,轻量化易于分享(应用3MB,引擎4KB)。4、2D图形复杂度可控,理论与实践相结合。5、易于扩展,与后期计划开发的补间动画、粒子效果、碰撞检测库无缝结合。技术选型背景:HarmonyOS2.0(api6)UI界面 :ArkUI(JSUI)系统能力 :java2D图形渲染引擎渲染引擎最小系统实现保留模式记录渲染状态、几何数据、变换信息。基于多叉树的场景图(Scence Gra
4、ph)层次渲染。支持精确点选,拥有完整的事件分发体系。自定义渲染系统坐标系变换(局部-世界坐标系)。基于时间的更新与重绘机制。一套小的算法库,包含多叉树寻址、矩阵运算、向量运算、单位化、递归更新等内容。Canvas绘制核心原理依赖于canvas标签所提供的渲染上下文(CanvasRenderingContext2D)对象,该对象包含了所有渲染所需要的属性和绘制命令。使用translate、rotate和scale这些方法时,变换的是依附在物体本体上的局部坐标系。所有绘制操作都是相对于变换后的物体的局部坐标系进行的。也就是说,在draw函数中定义物体时,其顶点坐标都是相对于局部坐标系原点的偏移。
5、这样的好处是,只要定义一次后,通过translate、 rotate和scale等操作,便可以将物体变换到任意位置,朝着任意角度,以及任意大小,这是一个非常棒的特性,可分离渲染数据源(不变性)及对渲染数据源的操作(可变性)。translate、rotate和scale这些局部坐标系变换方法都具有累积性,每次变换操作都是相对上一次结果的叠加,可以通过精心设计save和restore的层次来修改这种累积性。const context: CanvasRenderingContext2D = $(#canvas).getContext(2d)堆栈操作:save、restore .坐标系变换:trans
6、fer、rotate、scale、transform、setTransform属性配置:fillStyle、strokeStyle、lineWidth .绘制操作:moveTo、lineTo、arc、fillRect、stroke、drawImage .Canvas原生api示例旋转炮台context.save(); / 整个坦克移动和旋转(局部坐标系变换),注意变换顺序( trs:translate - rotate - scale ) context.translate(20, 20); context.rotate(30 * Math.PI / 180); context.scale(t
7、his.scaleX, this.scaleY); / 绘制坦克主体 context.strokeStyle= #000000 context.strokeRect(this.x, this.y, this.width, this.height) / 炮塔作为第二层,受第一层的save所影响 context.save(); / 炮塔作为整个坦克的一部分,是在上一级变换(trs)后的累积操作 context.rotate(30 * Math.PI / 180) ; / 绘制底座 + 炮管 + 炮口(省略部分代码) context.fillStyle = #FF0000 context.fllRe
8、ct(0, 0, 30, 2) context.restore();context.restore();Canvas的渲染堆栈context.save(); / 整个坦克移动和旋转(局部坐标系变换) context.translate(20, 20); context.rotate(30 * Math.PI / 180); / 绘制坦克主体 context.strokeStyle= #000000 context.strokeRect(this.x, this.y, this.width, this.height) / 炮塔作为第二层,受第一层的save所影响 context.save();
9、/ 炮塔作为整个坦克的一部分,是在上一级变换(trs)后的累积操作 context.rotate(30 * Math.PI / 180) ; / 绘制底座 + 炮管 + 炮口(省略部分代码) context.fillStyle = #FF0000 context.fllRect(0, 0, 30, 2) context.restore();context.restore();RenderState绘制属性:lineWdith/fillStyle/strokeStyle.仿射矩阵:累乘的最终结果RenderStateRenderState1RenderState2Canvas坐标转换原理1、使用
10、translate、rotate和scale这些方法时,变换的是依附在物体本体上的局部坐标系。2、所有绘制操作都是相对于变换后的局部坐标系所进行的。这是一个非常棒的特性,可分离渲染数据源(不变性)及对渲染数据源的操作(可变性)。3、translate、rotate和scale这些局部坐标系变换方法都具有累积性,每次变换操作都是相对上一次结果的叠加,可以通过精心设计save和restore的层次来修改这种累积性。渲染引擎架构矩阵矩阵(Matrix)是m个行(Row)和n个列(Column)构成的数组。 在数学中,矩阵(Matrix)是指纵横排列的二维数据表格,其本质是“向量之间的映射”。线性变换
11、是线性空间中的运动, 而矩阵就是用来描述这种变换的映射。矩阵运算:叉乘 A(mxn) X B(nxp) = C(mxp)矩阵特殊形式:单位矩阵、矩阵的逆、仿射变换矩阵矩阵的叉乘仿射变换矩阵缩放和旋转可以对图形进行平移变换包含平移的变换称为仿射变换,线性变换(缩放和旋转等)是仿射变换的特殊形式。我们只要知道,使用了仿射变换及齐次坐标系后,就能使用矩阵乘法来统一操作图形的缩放、旋转和平移等变换。左图是仿射变换矩阵的一般形式,矩阵中的每个元素都有一定含义。图形投影变换整体缩放变换矩阵运算平移矩阵缩放矩阵旋转矩阵(绕Z轴)旋转矩阵推导依据矩阵乘法法则,以上关系式用矩阵表示为:三维变换就是比二维变换多了
12、一个 z 轴了,当空间内的物体绕 z 轴旋转时,我们可以理解为在 xy 平面进行二位变换。实际推到过程与上式类似,只是 z 坐标保持不变:场景图树状“父-子”层级结构。父级数据变化后,同步影响所有子节点;而子节点的数据变化,不影响父节点。通过场景图的特性,可以实现控制解决各个层级精灵之间的坐标系变换数据同步问题。层次寻址与更新通过场景图的特性,可以实现控制解决各个层级精灵之间的坐标系变换数据同步问题。通过先根、深度优先遍历从根节点开始逐层累计矩阵相乘运算结果。事件收集/ 事件注册/ Application类接管事件的收集与派发,并包含以下几个关键功能:动画循环的启动和关闭。提供可以基于不同帧率
13、进行回调的定时器。需要子类实现的update抽象方法。需要子类实现的render抽象方法。需要子类实现的Touch事件分发或响应抽象方法。碰撞检测(精确点选)Touch事件全局坐标点,依次变换到每个精灵的局部坐标系中。1、依次计算每个精灵的世界-局部矩阵M(世界坐标矩阵求逆)2、确定用户Touch点世界坐标(x,y),表示为向量OP。3、通过矩阵变换向量得到全局坐标点在此精灵的局部坐标。4、确定该精灵的轮廓数据(0,0,width,height)5、确定碰撞检测方法:轴向包围盒(AABB)6、判断点是否在矩形内。事件分发事件分发采用后根、从右到左的广度优先遍历方式。Canvas属于立即绘制模式
14、,后绘制的图形层级高。因此从最后绘制的精灵往根节点方向,逐步进行触摸点的碰撞检测(后根层次)。精灵移动如何确定精灵组内的局部坐标偏移量?x1y11、已知用户Touch事件全局坐标 GlobalPt(x,y)2、命中检测(从下到上、从右到左、深度优先)求当前节点的 局部-世界变换矩阵 GlobalMatrix (从根节点开始到当前节点累计矩阵乘)通过矩阵求逆,得到 世界-局部变换矩阵 LocalMatrix通过矩阵 LocalMatrix 作用于向量GlobalPt,得出该GlobalPt在该精灵内局部坐标 LocalPt检测LocalPt与该精灵的碰撞3、通过LocalPt修正拖拽偏移量基于时
15、间的更新与重绘通过 requestAnimationFrame() 产生固定的调用频率,在每一帧内都进行一次场景图中的各层级矩阵运算,以计算所有元素每一帧的平移、旋转、缩放数据,并驱动Canvas绘制最新的画面。/ BaseApplication.js/ 启动应用主循环start() if (!this._start) this._start = true; / 核心代码 this._requestId = requestAnimationFrame(msec) = this.step(msec); ); / BaseApplication.jsstep(timeStamp) . 省略代码 t
16、his.update(elapsedMsec, intervalSec); this.render(); requestAnimationFrame(elapsedMsec) = this.step(elapsedMsec); );JavaScript与Java通信交互LocalParticleAbility通过 LocalParticleAbility 实现 js 调用 java 侧代码,以实现多设备协同能力。createLocalParticleAbility:获取java接口实例register:注册接口实例到框架层reply:PA端使用该接口向JS侧回调函数发送消息Java方法通过LP
17、A注册到MainAbility新建JSInterface.java,并实现LocalParticleAbility接口。(js无法实现动态权限申请)public class JSInterface implements LocalParticleAbility private final MainAbility mainAbility; public JSInterface(MainAbility mainAbility) this.mainAbility = mainAbility; 在MainAbility的onStart()方法中,通过调用register()方法,注册LocalPart
18、icleAbility接口实例到框架层。代码如下:public class MainAbility extends AceAbility private JSInterface jsInterface; Override public void onStart(Intent intent) super.onStart(intent); jsInterface = new JSInterface(this); jsInterface.register(this); JavaScript通过LPA调用java方法在index.js文件中,调用createLocalParticleAbility()
19、方法,得到Java中LocalParticleAbility接口实例,也即JSInterface调用getNetWorkIdAsync()方法,就会执行到Java中JSInterface定义的方法,参数result是Java端回调结果给JS端的数据var JS_PATH = com.likeyo.dreamwedding.manager.JSInterface;/以实际包名为准 export default data: localNetWorkId:, , async startFA() var that = this; this.javaInterface = createLocalPart
20、icleAbility(JS_PATH); / getNetWorkIdAsync方法名字要和Java中JSInterface类的getNetWorkIdAsync方法名字一致 this.javaInterface.getNetWorkIdAsync(result = that.localNetWorkId = result; this.showDeviceList(); ) Java回调数据给Javascript在requestPermissionAndGetNetWorkId()方法中,先获取分布式权限(这个权限仅是分布式拉起需要,在获取设备networkId时一起处理);在成功得到权限后
21、,再调用DeviceManager.createInstance()方法得到设备的networkId;最后调用LocalParticleAbility.Callback类的reply()方法(必须在子线程调用,实现异步操作),将获取到的设备networkId传递给JS中。public class MainAbility extends AceAbility private LocalParticleAbility.Callback callback; public void setCallback(LocalParticleAbility.Callback callback) this.cal
22、lback = callback; public void requestPermissionAndGetNetWorkId() permission = new HPermission(); permission.requestPermissions(this, this:getNetWorkId); private void jsCallBack(String networkId) if (callback != null) new Thread() - callback.reply(networkId).start(); 流程图动态申请权限获取在线设备拉起远程FA动态申请权限拉起远程FA单例发送控制指令指令完成JSJavaJSJava华为分享华为分享1、创建IDL接口文件 集成IDL接口,用于建立分享方与华为分享的交互通道,完成后续服务分享过程。 在“java”目录同级目录创建“idl”接口目录:com/huawei/hwshare/third(固定路径),然后创建名为IHwShareCallback.idl和IHwShareService.idl的IDL文件。华为分享通过IDE自
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 布置摆设出让合同范例
- 采购健身设备合同范例
- 2024年多媒体接单系统项目可行性研究报告
- 2024年双速多速三相异步电动机项目可行性研究报告
- 2024年全自动无人值守换热机组项目可行性研究报告
- 团队合作培训课件-完成版
- 2024至2030年车门板项目投资价值分析报告
- 2024至2030年网络安全主板项目投资价值分析报告
- 2024至2030年玉石粉项目投资价值分析报告
- 2024至2030年横流风扇项目投资价值分析报告
- 2023阻塞性睡眠呼吸暂停与难治性高血压(全文)
- 滦平县兴华昌顺矿业有限公司西洼子群兴铁矿矿山地质环境保护与治理恢复方案
- 《刻舟求剑》课件 (共27张PPT)
- 耕地占补平衡动态监管系统培训讲解
- 湘教版八上音乐 都达尔和玛利亚 课件(共19张PPT)
- 2022年山东省济南市统考专升本管理学真题(含答案)
- 劳动教育知到章节答案智慧树2023年杭州医学院
- 电影音乐欣赏知到章节答案智慧树2023年华南农业大学
- 顽危犯转化个例
- 《食品安全培训资料》
- 染整习题及答案
评论
0/150
提交评论