HarmonyOS APP实战-画图APP - 第7篇:文本绘制功能

发布时间:2026/7/12 22:25:20

HarmonyOS APP实战-画图APP - 第7篇:文本绘制功能
HarmonyOS APP实战-画图APP - 第7篇在画布上添加文字1. 开篇在第6篇中我们完成了绘制模式的切换与交互反馈优化。通过DrawMode枚举Rect、Circle、FreeDraw管理当前绘制模式在工具栏中实现了高亮选中状态并在画布触摸事件中根据模式调用不同的绘制逻辑drawRect、drawCircle、drawPath。顶部显示当前模式标签用户操作时获得明确的视觉反馈。本篇我们将为画图APP增加文字绘制功能。文字是图形创作中不可或缺的元素——添加标题、批注、签名等场景都需要它在画布上呈现。实现思路是用户通过一个弹出窗口输入文字、选择字体大小和颜色然后在画布上点击或拖拽放置文本。我们将使用ohos.graphics.drawing模块的drawTextAPI在Canvas上渲染文字并实现可拖拽定位的交互。2. 核心实现2.1 基础配置首先导入绘制文字所需的模块并扩展我们的状态管理。在Index.ets顶部添加导入。// Index.ets — 基础配置与模块导入import{CanvasRenderingContext2D}fromohos.graphics.drawing;// 定义文字对象的数据结构interfaceTextItem{content:string;// 文字内容fontSize:number;// 字体大小pxcolor:string;// 颜色十六进制字符串x:number;// 文本左上角x坐标y:number;// 文本左上角y坐标width?:number;// 文本渲染宽度用于碰撞检测height?:number;// 文本渲染高度用于碰撞检测}// 扩展DrawMode枚举添加TEXT模式enumDrawMode{Rect,Circle,FreeDraw,Text// 新增文字模式}关键点说明TextItem接口存储文字的所有属性width和height用于触摸命中检测判断用户是否点到文本区域。DrawMode.Text作为新的绘制模式与之前的形状/画笔模式平级。后续我们需要在画布渲染循环中遍历TextItem数组并调用drawText。2.2 FontPicker组件字体大小与颜色选择器用户输入文字时需要同时选择字体大小和颜色。我们创建一个独立的FontPicker组件它显示一个自定义弹窗或内嵌UI。// components/FontPicker.ets — 字体大小与颜色选择器Componentexportstruct FontPicker{ConsumefontSize:number;// 从父组件继承的字体大小ConsumefontColor:string;// 从父组件继承的字体颜色build(){Column(){// 字体大小滑块Row(){Text(字体大小:).fontSize(16).width(80)Slider({value:this.fontSize,min:12,max:120,step:4,style:SliderStyle.OutSet}).width(200).onChange((value:number){this.fontSizevalue;// 通过Consume双向绑定})}.margin({bottom:12})// 颜色选择器预设色块Row(){Text(字体颜色:).fontSize(16).width(80)// 使用Grid展示常用颜色ForEach([#000000,#FF0000,#00FF00,#0000FF,#FFFF00,#FF00FF,#00FFFF,#FFFFFF],(color:string){Circle({width:30,height:30}).fill(color).stroke(this.fontColorcolor?Color.Black:Color.White).strokeWidth(3).margin(4).onClick((){this.fontColorcolor;})})}}.padding(12).backgroundColor(#F5F5F5).borderRadius(8)}}关键点说明使用Consume装饰器实现父子组件双向数据绑定父组件提供fontSize和fontColor两个状态变量。Slider组件控制字体大小范围12~120px步进4px。颜色选择器用8个预设色块点击直接赋值实际项目可扩展为完整的色盘参考第5篇的颜色选择逻辑。此组件被嵌入到文本输入弹窗中跟随弹窗显示。2.3 文本输入与拖拽放置模块TextTool核心逻辑当用户点击工具栏的“文字”按钮后模式切换为Text。点击画布任意位置弹出输入框让用户输入文字内容并确认。文字对象随即出现在点击位置用户可继续拖拽调整位置。// components/TextTool.ets — 文字输入与拖拽放置模块Componentexportstruct TextTool{privatecanvasCtx:CanvasRenderingContext2D;LinktextItems:TextItem[];// 画布上所有文字对象StatefontSize:number36;// 当前字体大小StatefontColor:string#000000;// 当前字体颜色StateisAddingText:booleanfalse;// 是否正在输入文字StateinputContent:string;// 输入框内容privatetextDialogController:CustomDialogController;build(){Column(){// 文字模式专用按钮Button(添加文字).fontSize(16).onClick((){this.isAddingTexttrue;// 弹出自定义对话框用于输入文字this.showTextInputDialog();})}}// 显示文字输入对话框使用CustomDialogshowTextInputDialog(){this.textDialogControllernewCustomDialogController({builder:TextInputDialog({fontSize:this.fontSize,fontColor:this.fontColor,onConfirm:(content:string){this.inputContentcontent;this.isAddingTexttrue;this.textDialogController.close();},onCancel:(){this.isAddingTextfalse;this.textDialogController.close();}}),autoCancel:true,alignment:DialogAlignment.Center,offset:{dx:0,dy:-80}});this.textDialogController.open();}// 在画布上放置文字的触摸事件处理handleCanvasTouch(event:TouchEvent):void{if(this.isAddingTextthis.inputContent){// 获取触摸点坐标相对于画布consttouchXevent.touches[0].x;consttouchYevent.touches[0].y;// 创建一个新的TextItem并添加到textItems数组constnewText:TextItem{content:this.inputContent,fontSize:this.fontSize,color:this.fontColor,x:touchX,y:touchY};this.textItems[...this.textItems,newText];// 重置状态准备下一次输入this.inputContent;this.isAddingTextfalse;// 重绘画布this.redrawCanvas();}else{// 尝试拖拽已有的文字对象this.dragTextItem(event);}}// 拖拽文字在触摸移动时更新坐标dragTextItem(event:TouchEvent){consttouchXevent.touches[0].x;consttouchYevent.touches[0].y;// 遍历文字列表检查触摸点是否落在某个文字区域内for(letithis.textItems.length-1;i0;i--){constitemthis.textItems[i];// 计算文字区域估算宽度content长度*fontSize*0.6高度fontSize*1.2constestimatedWidthitem.content.length*item.fontSize*0.6;constestimatedHeightitem.fontSize*1.2;// 判断触摸点是否在文字矩形区域内if(touchXitem.xtouchXitem.xestimatedWidthtouchYitem.y-estimatedHeighttouchYitem.y){// 更新坐标if(event.typeTouchType.Move){item.xtouchX-estimatedWidth/2;item.ytouchY;this.textItems[...this.textItems];// 触发UI更新this.redrawCanvas();}break;}}}// 重新绘制画布包含所有文字redrawCanvas(){if(!this.canvasCtx)return;// 清空画布并重新绘制所有图形此处简化实际需结合之前的绘制指令this.canvasCtx.clearRect(0,0,this.canvasCtx.width,this.canvasCtx.height);// ... 重新绘制之前的形状 画笔轨迹省略与第3-6篇代码集成this.drawAllTexts();}// 遍历文字列表绘制所有文字drawAllTexts(){if(!this.canvasCtx)return;this.textItems.forEach((item:TextItem){this.canvasCtx.font${item.fontSize}px sans-serif;this.canvasCtx.fillStyleitem.color;this.canvasCtx.textAlignleft;this.canvasCtx.textBaselinetop;this.canvasCtx.fillText(item.content,item.x,item.y);});}}关键点说明使用CustomDialogController弹出输入对话框TextInputDialog组件需另定义用于输入文字内容。触摸事件处理当处于“添加文字”状态且内容非空时触摸点即文字放置位置否则尝试拖拽已有文字。estimatedWidth和estimatedHeight是粗略估算的文字区域用于触摸命中判断。精确计算可使用CanvasRenderingContext2D.measureText但因异步问题本实现采用估算方式仍可满足基本交互。drawAllTexts方法在每次重绘时调用使用fillText绘制文字。font、fillStyle依据TextItem属性动态设置。2.4 在画布组件中集成文字绘制最后将TextTool集成到主画布组件中在渲染循环中调用文字绘制。// Index.ets — 主画布组件核心代码片段Componentstruct DrawingCanvas{privatecanvasCtx:CanvasRenderingContext2DnewCanvasRenderingContext2D();StatecurrentMode:DrawModeDrawMode.Rect;StatetextItems:TextItem[][];// 文字对象数组privatetextTool:TextToolnewTextTool();build(){Column(){// ... 工具栏省略包含模式切换按钮// 文字模式下显示TextTool组件if(this.currentModeDrawMode.Text){TextTool({canvasCtx:this.canvasCtx,textItems:$textItems}).width(100%).height(60)}// 画布区域Canvas(this.canvasCtx).width(100%).layoutWeight(1).backgroundColor(#FFFFFF).onTouch((event:TouchEvent){if(this.currentModeDrawMode.Text){this.textTool.handleCanvasTouch(event);}else{// 原有形状/画笔模式处理略}})}.width(100%).height(100%)}}关键点说明TextItem数组通过State声明驱动UI更新。触摸事件根据currentMode分发文字模式调用TextTool.handleCanvasTouch其他模式走原有逻辑。TextTool组件接收canvasCtx和textItems引用实现跨组件的协作。3. 运行验证在DevEco Studio中运行项目按照以下步骤验证点击工具栏新增的“文字”按钮模式切换为文字模式按钮高亮。点击画布任意位置弹出文字输入对话框。输入文字内容例如“Hello HarmonyOS”通过滑块调整字体大小为48px选择红色。点击“确定”后输入的文字出现在点击位置。再次在文字区域内触摸并拖动文字跟随手指移动。重复上述步骤添加多个文字可叠加在之前的图形之上。预期表现文字清晰渲染颜色和大小与设置一致拖拽行为流畅触摸命中区域基本准确。4. 小结与预告本篇完成了文本绘制功能在画图APP中的集成。核心产出包括定义了TextItem数据结构支持存储内容、字体、颜色、坐标。实现了FontPicker组件提供字体大小和颜色选择UI。实现了TextTool模块包含文字输入对话框、触摸放置和拖拽逻辑。使用CanvasRenderingContext2D.fillTextAPI渲染文字并与原有绘制逻辑共存。至此画图APP已支持矩形、圆形、自由画笔和文字四种绘制元素用户的创作能力大大增强。下一篇《使用effectKit处理图像》将引入ohos.effectKit模块为画布内容添加亮度调节、模糊化、灰度调节等图像特效。届时用户在绘制完成后可选择应用滤镜实现更丰富的视觉效果。我们将在第8篇中构建特效面板并集成到工具栏中。

相关新闻

Open Source Candies生态系统分析:开源项目如何利用免费服务成长

Open Source Candies生态系统分析:开源项目如何利用免费服务成长

2026/7/12 22:15:20

Open Source Candies生态系统分析:开源项目如何利用免费服务成长 【免费下载链接】opensource-candies Free stuff for open source projects 项目地址: https://gitcode.com/gh_mirrors/op/opensource-candies 在开源项目的成长过程中,资源和工具…

Orchestra工具生态系统全解析:从内置工具到自定义工具开发

Orchestra工具生态系统全解析:从内置工具到自定义工具开发

2026/7/12 22:15:20

Orchestra工具生态系统全解析:从内置工具到自定义工具开发 【免费下载链接】orchestra Cognitive Architectures for Multi-Agent Teams 项目地址: https://gitcode.com/gh_mirrors/orchestr/orchestra Orchestra是一个强大的多智能体协作框架,其…

Osg 开发一:OpenSceneGraph 介绍及开发环境设置

Osg 开发一:OpenSceneGraph 介绍及开发环境设置

2026/7/12 22:15:20

文章目录一 OpenSceneGraph 简介1 什么是 OpenSceneGraph2 OSG 中国3 OSG 组成模块二 OSG 开发1 开发环境2 环境设置3 Hello OSG 工程其他一 OpenSceneGraph 简介 1 什么是 OpenSceneGraph OSG 是一个开源的场景图形管理开发库,主要为图形图像应用程序的开发提供场…

99.1.智能门禁-指纹+RFID+密码-基于STM32单片机物联网设计【硬件+APP+云平台】

99.1.智能门禁-指纹+RFID+密码-基于STM32单片机物联网设计【硬件+APP+云平台】

2026/7/13 0:15:25

(1)硬件端 1. STM32F103C8T6:用于所有程序的中控和模块数据通信; 2. 0.96寸OLDE:用于显示当前设备状态; 3. 指纹模块(AS608):实现指纹录入以及开锁功能功能; …

176.离散产线通用分拣功能块:黑白物料分类、传送带启停联锁、故障自锁,包装 / 物流流水线直接移植

176.离散产线通用分拣功能块:黑白物料分类、传送带启停联锁、故障自锁,包装 / 物流流水线直接移植

2026/7/13 0:15:25

摘要 可编程逻辑控制器(PLC)是现代工业自动化的核心设备,广泛应用于生产线控制、过程监控与离散制造场景。本文从PLC的基本原理出发,深入解析其扫描周期、I/O映射与梯形图/ST语言编程模型,并通过一个完整的物料分拣系统案例,提供可直接运行的ST语言代码与仿真验证步骤。…

175.别把急停写在程序末尾!**前置 RETURN 最高优先级安全架构,工业强制标准规范写法**

175.别把急停写在程序末尾!**前置 RETURN 最高优先级安全架构,工业强制标准规范写法**

2026/7/13 0:15:25

摘要 可编程逻辑控制器(PLC)是工业自动化领域最核心的控制设备。本文从PLC的硬件架构与扫描周期原理出发,以IEC 61131-3标准的结构化文本(ST)语言为主线,系统讲解PLC编程的核心逻辑。通过一个完整的工业罐装生产线控制案例,提供可直接运行的ST代码,并详细分析运行结果…

174.带超时故障报警、双推杆互锁保护、自动计数功能的 PLC 状态机分拣程序开发

174.带超时故障报警、双推杆互锁保护、自动计数功能的 PLC 状态机分拣程序开发

2026/7/13 0:15:25

摘要 可编程逻辑控制器(PLC)是工业自动化领域的核心控制设备,广泛应用于制造业、能源、交通等行业。本文从工程实践角度出发,系统阐述PLC的工作原理、IEC 61131-3编程标准、典型应用场景,并提供完整的梯形图与结构化文本代码示例。通过本文,读者将掌握PLC的硬件架构、扫…

173.具备 4-20mA 模拟量线性转换、断线故障检测、超温超压联锁保护功能的 PLC 温控程序开发

173.具备 4-20mA 模拟量线性转换、断线故障检测、超温超压联锁保护功能的 PLC 温控程序开发

2026/7/13 0:15:25

摘要 可编程逻辑控制器(PLC)是工业自动化领域的核心控制设备,广泛应用于生产线控制、过程控制、运动控制等场景。本文从PLC的底层硬件架构出发,深入解析扫描周期、梯形图与结构化文本的对应关系,并以西门子S7-1200为硬件平台,提供一套完整的从硬件组态、变量声明到结构化…

Palworld存档编辑完全掌握:从零开始实现游戏数据可视化修改

Palworld存档编辑完全掌握:从零开始实现游戏数据可视化修改

2026/7/13 0:05:25

Palworld存档编辑完全掌握:从零开始实现游戏数据可视化修改 【免费下载链接】palworld-save-tools Tools for converting Palworld .sav files to JSON and back 项目地址: https://gitcode.com/gh_mirrors/pa/palworld-save-tools 你是否曾经想要调整Palwor…

Unity游戏文本翻译架构深度解析:XUnity.AutoTranslator的技术实现与工程实践

Unity游戏文本翻译架构深度解析:XUnity.AutoTranslator的技术实现与工程实践

2026/7/12 0:03:42

Unity游戏文本翻译架构深度解析:XUnity.AutoTranslator的技术实现与工程实践 【免费下载链接】XUnity.AutoTranslator 项目地址: https://gitcode.com/gh_mirrors/xu/XUnity.AutoTranslator XUnity.AutoTranslator作为Unity游戏社区中最成熟的文本翻译解决方…

openEuler Raspberry Pi Kernel设备驱动开发指南:为树莓派硬件添加支持

openEuler Raspberry Pi Kernel设备驱动开发指南:为树莓派硬件添加支持

2026/7/12 0:03:42

openEuler Raspberry Pi Kernel设备驱动开发指南:为树莓派硬件添加支持 【免费下载链接】raspberrypi-kernel It provides openEuler kernel source for Raspberry Pi 项目地址: https://gitcode.com/openeuler/raspberrypi-kernel 前往项目官网免费下载&…

openEuler系统集成测试实战:基于smoke-test套件的环境验证技巧

openEuler系统集成测试实战:基于smoke-test套件的环境验证技巧

2026/7/12 0:03:42

openEuler系统集成测试实战:基于smoke-test套件的环境验证技巧 【免费下载链接】integration-test The repo contains test suits for system integration test 项目地址: https://gitcode.com/openeuler/integration-test 前往项目官网免费下载:…

卡梅德生物技术快报|纯化重组蛋白:变异链球菌 SepM 截短蛋白载体构建、诱导优化与纯化重组蛋白全套参数方案

卡梅德生物技术快报|纯化重组蛋白:变异链球菌 SepM 截短蛋白载体构建、诱导优化与纯化重组蛋白全套参数方案

2026/7/13 0:05:25

1 研究背景与现存技术痛点(提出问题)在口腔微生物分子机制研究中,SepM 蛋白酶是调控变异链球菌群体感应、致龋菌素合成的核心功能蛋白,体外功能验证、抗体开发均依赖高纯度可溶性 SepM 蛋白。当前原核表达体系针对 SepM 存在三大技…

卡梅德生物技术快报|重组蛋白的表达和纯化:IMAC 金属螯合色谱全流程工艺手册|基质 - 配基 - 金属离子匹配与蛋白质分离纯化参数优化

卡梅德生物技术快报|重组蛋白的表达和纯化:IMAC 金属螯合色谱全流程工艺手册|基质 - 配基 - 金属离子匹配与蛋白质分离纯化参数优化

2026/7/13 0:05:25

1 研究背景与现存技术痛点(提出问题)基因工程、蛋白质组学、生物制药研发流程中,蛋白质分离纯化是决定下游实验成败的关键环节。当前实验室常规蛋白质分离纯化工艺存在三类难以标准化的技术瓶颈:传统离子交换、分子筛层析无特异性…

卡梅德生物技术快报|蛋白质分离纯化:肠激酶可溶性原核表达 + 两步层析全参数|标准化蛋白质分离纯化 SOP

卡梅德生物技术快报|蛋白质分离纯化:肠激酶可溶性原核表达 + 两步层析全参数|标准化蛋白质分离纯化 SOP

2026/7/13 0:05:25

研究痛点提出(提出问题)重组肠激酶是融合标签切除核心工具酶,当前原核表达体系存在三大标准化难题,直接阻碍可复现的蛋白质分离纯化流程搭建:Trx、GST、单 SUMO 标签融合产物绝大多数为包涵体,沉淀占比超 9…