尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
HarmonyOS APP实战-画图APP - 第14篇:可变帧率与性能优化
HarmonyOS APP实战-画图APP - 第14篇使用displaySync定制绘制帧率开篇上一篇我们完成了本地数据库存储与读取功能通过关系型数据库RdbStore保存了画作元数据名称、创建时间、缩略图路径并实现了画作列表页面支持从列表加载已有画作继续编辑。数据库模块是画图APP的数据持久化基石。本篇将聚焦性能优化——根据绘制内容的复杂度动态调整绘制帧率。画图APP在画笔手绘时需要高帧率60fps保证跟手性而空闲状态或显示静态图形时可以降低帧率至30fps以减少功耗。HarmonyOS提供了displaySyncAPI允许开发者针对自绘制内容指定不同的目标帧率。我们将封装一个FrameRateController模块并在DrawingCanvas组件中集成它实现按需切换帧率。核心实现基础配置导入与常量定义首先在模块顶部导入displaySync并定义帧率常量。// FrameRateController.etsimport{displaySync}fromohos.graphics.displaySync;/** * 帧率常量 */exportconstFRAME_RATE_HIGH60;// 高帧率模式画笔绘制时exportconstFRAME_RATE_LOW30;// 低帧率模式静止或浏览时关键点说明ohos.graphics.displaySync是ArkGraphics 2D提供的可变帧率能力模块。帧率值单位是fps帧每秒60fps适合手绘追踪30fps满足静态显示且降低功耗。核心逻辑FrameRateController类FrameRateController负责创建和管理DisplaySync实例并根据业务状态设置目标帧率。// FrameRateController.etsexportclassFrameRateController{privatedisplaySyncInstance:displaySync.DisplaySync|nullnull;privateisRunning:booleanfalse;privatecurrentRate:numberFRAME_RATE_LOW;/** * 初始化DisplaySync实例 * param requestId 请求标识用于区分不同绘制场景 */publicasyncinit(requestId:string):Promisevoid{if(this.displaySyncInstance){return;}try{this.displaySyncInstanceawaitdisplaySync.create(requestId);console.info(FrameRateController: DisplaySync created with requestId${requestId});}catch(err){console.error(FrameRateController: create failed, error${JSON.stringify(err)});}}/** * 启动帧率控制 * param frameCallback 每帧回调参数为时间戳 */publicstart(frameCallback:(timestamp:number)void):void{if(!this.displaySyncInstance||this.isRunning){return;}this.displaySyncInstance.start(frameCallback);this.isRunningtrue;console.info(FrameRateController: started);}/** * 停止帧率控制 */publicstop():void{if(!this.displaySyncInstance||!this.isRunning){return;}this.displaySyncInstance.stop();this.isRunningfalse;console.info(FrameRateController: stopped);}/** * 更新目标帧率 * param rate 新的帧率值fps */publicupdateFrameRate(rate:number):void{if(!this.displaySyncInstance){console.warn(FrameRateController: instance not initialized);return;}try{this.displaySyncInstance.setExpectedFrameRate(rate);this.currentRaterate;console.info(FrameRateController: frame rate updated to${rate}fps);}catch(err){console.error(FrameRateController: setExpectedFrameRate failed, error${JSON.stringify(err)});}}/** * 销毁DisplaySync实例 */publicdestroy():void{if(this.displaySyncInstance){this.displaySyncInstance.destroy();this.displaySyncInstancenull;this.isRunningfalse;console.info(FrameRateController: destroyed);}}/** * 获取当前帧率 */publicgetCurrentRate():number{returnthis.currentRate;}}关键点说明displaySync.create(requestId)是一个异步方法返回PromiseDisplaySync实例。setExpectedFrameRate(rate)设置期望帧率系统会尽量按照该值调度。start(callback)开始帧率控制回调参数为时间戳纳秒可用于驱动动画循环。destroy()释放资源在页面销毁时调用。实际项目中帧率回调可以作为绘制驱动的定时器替代setInterval或requestAnimationFrame提供更精确的帧同步。完整模块集成到DrawingCanvas组件DrawingCanvas是画图APP的核心绘制组件。我们在其中集成FrameRateController在触摸开始/移动时切换到高帧率触摸结束或闲置时降回低帧率。同时为了兼容原有绘制逻辑我们将帧率回调绑定到画布重绘操作。// DrawingCanvas.ets简化版仅展示集成逻辑import{CanvasRenderingContext2D}fromohos.graphics.ui;import{FrameRateController,FRAME_RATE_HIGH,FRAME_RATE_LOW}from./FrameRateController;import{Point,DrawCommand}from../model/DrawCommand;// 假设自定义模型Componentexportstruct DrawingCanvas{privatesettings:RenderingContextSettingsnewRenderingContextSettings(true);privatecontext:CanvasRenderingContext2DnewCanvasRenderingContext2D(this.settings);privateframeCtrl:FrameRateControllernewFrameRateController();privateisDrawing:booleanfalse;privatelastTouch:Point{x:0,y:0};// ... 其他属性aboutToAppear(){// 初始化DisplaySyncrequestId可自定义this.frameCtrl.init(drawing_canvas_main).then((){// 启动帧率控制将回调连接到画布刷新this.frameCtrl.start((timestamp:number){// 这里可以驱动持续的绘制更新例如动画// 对于手绘我们只在触摸事件中局部重绘此回调暂不开启批量重绘// 但保持帧率控制活跃});// 初始设为低帧率this.frameCtrl.updateFrameRate(FRAME_RATE_LOW);});}onTouch(event:TouchEvent){if(!this.frameCtrl)return;switch(event.type){caseTouchType.Down:this.isDrawingtrue;// 触摸开始时切换到高帧率保证跟手this.frameCtrl.updateFrameRate(FRAME_RATE_HIGH);this.lastTouch.xevent.touches[0].x;this.lastTouch.yevent.touches[0].y;// 开始新路径this.startNewPath(this.lastTouch);break;caseTouchType.Move:if(this.isDrawing){constcurrent{x:event.touches[0].x,y:event.touches[0].y};// 添加点到当前路径并绘制this.addPointToPath(current);this.lastTouchcurrent;}break;caseTouchType.Up:caseTouchType.Cancel:// 绘制结束恢复低帧率if(this.isDrawing){this.finishPath();this.isDrawingfalse;this.frameCtrl.updateFrameRate(FRAME_RATE_LOW);}break;}}privatestartNewPath(point:Point):void{// 原有逻辑开始一个新的Path}privateaddPointToPath(point:Point):void{// 原有逻辑向Path增加点并调用context.drawPath()}privatefinishPath():void{// 原有逻辑结束路径并保存到历史}aboutToDisappear(){this.frameCtrl.stop();this.frameCtrl.destroy();}build(){Canvas(this.context).width(100%).height(100%).onTouch((event:TouchEvent)this.onTouch(event))}}议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_urlplaceholder.pngpos_idimg-K54aM3fo-1783906018434)关键点说明aboutToAppear中初始化FrameRateController并启动默认低帧率。在onTouch的Down事件中更新为高帧率Up或Cancel时恢复低帧率。注意帧率回调本身不涉及重绘但保持start可以让系统按照目标帧率调度实际绘制仍由触摸事件触发。aboutToDisappear中停止并销毁实例防止内存泄漏。如果后续需要实现动画绘制如动态渐变、粒子效果可以利用frameCallback的时间戳驱动逐帧重绘此时帧率控制效益更明显。运行验证在画图APP中打开任意画布文件或新建画布用手指在画布上绘制当手指按下并移动时CPU/GPU会按60fps渲染轨迹体验流畅跟手。当手指抬起后帧率会降为30fps此时进行菜单操作或查看静态内容手机功耗降低。开发者可以通过DevEco Studio的Profiler工具查看帧率变化运行APP点击“性能分析”在“帧率时间线”中观察绘制时段帧率约60fps闲置时段约30fps。如果未看到切换请确认displaySync已正确初始化和权限设置无需额外权限。另外模拟器可能不完全支持帧率动态调节建议在真机上测试。小结与预告本篇实现了画图APP的帧率动态调节功能通过FrameRateController模块封装displaySyncAPI根据绘制活动自动切换60fps和30fps在保持手绘跟手性的同时减少闲置功耗。该模块是性能优化的重要一环可直接复用至其他自绘制场景。下一篇《使用overdraw工具检测性能》将介绍如何利用HarmonyOS的过度绘制调试工具Overdraw Debug分析画布绘制效率识别冗余绘制层次并通过Canvas的clip、clearRect等技术优化绘制指令进一步提升流畅度。
RELATED

相关推荐

HarmonyOS APP实战-画图APP - 第12篇:离线图像处理与保存

HarmonyOS APP实战-画图APP - 第12篇:离线图像处理与保存

HarmonyOS APP实战-画图APP - 第12篇&#xff1a;导出与加载图片文件 1. 开篇 上一篇我们完成了操作历史管理模块&#xff0c;实现了基于命令模式的撤销/重做栈&#xff1a;HistoryManager 类维护了两个 Stack<Command> 实例&#xff0c;每次绘制操作封装为 Command 对象…

📅 2026/9/11 17:13:13
2026年多商户商城系统哪个好?商家入驻、分账和权限对比

2026年多商户商城系统哪个好?商家入驻、分账和权限对比

2026年多商户商城系统哪个好&#xff1f;商家入驻、分账和权限对比多商户商城系统哪个好&#xff0c;不能只看能不能上架商品。平台型业务和单店商城不一样&#xff0c;核心在商家能不能入驻&#xff0c;平台能不能审核商品&#xff0c;订单和售后责任怎么划分&#xff0c;平台…

📅 2026/8/10 5:57:43
基于改进 ICEEMDAN 的火电 - 蓄电池 - 飞轮混合储能联合调频协同控制策略研究(Matlab代码实现)

基于改进 ICEEMDAN 的火电 - 蓄电池 - 飞轮混合储能联合调频协同控制策略研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 &#x1f381…

📅 2026/8/10 13:48:56
MORE NEWS

更多资讯

📰

FPGA UART接收器RTL设计:抗干扰采样与物理层鲁棒性实现

1. 项目概述&#xff1a;这不是教科书里的UART&#xff0c;而是能跑在FPGA上、接得住真实串口数据的RX接收器 “第04讲&#xff1a;UART接收器 RX RTL 设计”——光看标题&#xff0c;你可能以为这是某门数字电路课的作业编号。但如果你正蹲在实验室调一块Xilinx Artix-7开发板…

📰

20分钟快速构建LangChain智能体:文档问答实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

VS Code + STM32 嵌入式开发环境搭建:从 Keil 迁移到 AI 编程

我从 Keil 转到 VS Code 折腾嵌入式开发&#xff0c;算起来也有几年了。期间踩过不少坑&#xff0c;也积累了一些经验。最近不少朋友在问“如何利用 AI 开发嵌入式软件”&#xff0c;问的最多的就是环境怎么搭。这篇就专门聊聊 VS Code 与 STM32 扩展工具的安装配置&#xff0c…

📰

Java工程师转型Agent开发:RAG系统架构与优化实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

阿里云MySQL选型指南:自建vs瑶池RDS决策路径

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

AI绘画本地部署完全指南:1元/小时成本起步,搭好自己的AI绘画工作台

AI绘画本地部署完全指南&#xff1a;1元/小时成本起步&#xff0c;搭好自己的AI绘画工作台 【免费下载链接】awesome-ai-painting AI绘画资料合集&#xff08;包含国内外可使用平台、使用教程、参数教程、部署教程、业界新闻等等&#xff09; Stable diffusion、AnimateDiff、S…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬