HarmonyOS6 ArkTS 自定义绘制DrawModifier实战使用文档

发布时间:2026/5/19 22:20:26

HarmonyOS6 ArkTS 自定义绘制DrawModifier实战使用文档 文章目录一、DrawModifier核心概念DrawModifier核心重载方法说明二、自定义DrawModifier实现详解2.1 基础依赖导入2.2 全层级自定义绘制修饰器MyFullDrawModifier核心成员变量核心方法重载逻辑2.3 纯前景层自定义绘制修饰器MyFrontDrawModifier三、动画联动与主动重绘逻辑3.1 动画控制器创建create方法3.2 交互控制逻辑四、组件绑定drawModifier属性五、代码总结一、DrawModifier核心概念DrawModifier是HarmonyOS ArkTS提供的自定义绘制属性修饰器属于组件通用属性允许开发者通过继承DrawModifier类重写对应绘制方法在组件的背景层、内容层、前景层实现自定义图形绘制完全脱离原生组件样式限制实现高度定制化的UI效果。根据官方规范DrawModifier包含三个核心重载方法分别对应组件不同绘制层级绘制优先级为drawBehind背景层 组件自身内容 drawContent内容层 drawFront前景层三个方法可单独重载或组合重载灵活适配不同绘制需求配合UIContext和Canvas API可实现矩形、圆形、自定义路径等各类图形绘制。DrawModifier核心重载方法说明drawBehind绘制组件背景层在组件自身背景之后、底层内容之前渲染用于自定义组件背景图形drawContent绘制组件内容层覆盖组件默认内容在背景层之后、前景层之前渲染用于替换组件原有内容drawFront绘制组件前景层在组件所有内容之上渲染会覆盖组件自身内容和drawContent绘制内容用于悬浮图形、标记、装饰等场景invalidate()DrawModifier内置方法主动触发组件重绘动态修改绘制参数后必须调用否则样式无法实时更新二、自定义DrawModifier实现详解2.1 基础依赖导入代码开头导入ArkGraphics2D绘图模块与Animator动画模块是实现自定义绘制和动画联动的基础依赖必须按照官方要求导入缺一不可kit.ArkGraphics2D提供Brush画笔、Canvas等2D绘图API用于绘制各类图形kit.ArkUI提供AnimatorResult动画相关接口用于实现绘制参数的动态过渡2.2 全层级自定义绘制修饰器MyFullDrawModifier该类完整实现DrawModifier的三个核心绘制方法覆盖组件背景、内容、前景全层级是官方推荐的完整自定义绘制写法适配复杂定制化UI场景核心成员变量scaleX/scaleY自定义缩放参数控制绘制图形的尺寸用于实现动态缩放效果uiContextUI上下文对象通过构造函数传入用于vp和px单位转换vp2px适配不同屏幕密度符合鸿蒙多终端适配规范核心方法重载逻辑drawBehind创建红色画笔画布绘制居中矩形作为组件背景层图形矩形尺寸跟随scaleX/scaleY动态缩放drawContent创建绿色画笔画布绘制居中小矩形作为组件内容层图形尺寸小于背景矩形形成层级叠加drawFront创建蓝色画笔画布绘制居中圆形作为组件前景层图形尺寸基于缩放参数平均值计算覆盖在内容层之上2.3 纯前景层自定义绘制修饰器MyFrontDrawModifier该类仅重载drawFront单一方法属于精简版自定义修饰器仅实现前景层圆形绘制不影响组件背景和原有内容适合单纯添加前景装饰、标记的轻量场景充分体现DrawModifier可单独重载单一方法的灵活性贴合官方文档中“按需重载方法”的规范。三、动画联动与主动重绘逻辑3.1 动画控制器创建create方法通过UIContext创建Animator动画对象配置动画时长1000ms、缓动曲线ease、起始值与结束值定义帧回调方法处理动态参数动画帧回调中实时计算scaleX和scaleY的值通过绝对值实现图形从正常到缩小再恢复的弹性效果参数修改完成后调用self.modifier.invalidate()主动触发DrawModifier重绘保证图形尺寸实时更新3.2 交互控制逻辑create按钮初始化动画控制器仅需调用一次避免重复创建造成资源浪费play按钮启动动画触发动态缩放效果验证动画与自定义绘制的联动能力changeModifier按钮通过计数器切换绑定的修饰器在全层级绘制和纯前景层绘制之间切换展示不同修饰器的绘制效果文本组件点击手动递减scaleX/scaleY参数逐步缩小绘制图形验证静态交互修改绘制参数的逻辑四、组件绑定drawModifier属性绑定语法.drawModifier(this.modifier)modifier为State修饰的响应式变量保证修饰器切换时组件自动更新State修饰modifier变量是实现动态切换修饰器的关键变量变更后组件会重新绑定新的绘制修饰器并刷新五、代码// xxx.ets import { drawing } from kit.ArkGraphics2D; import { AnimatorResult } from kit.ArkUI; // 继承DrawModifier实现自定义绘制控制器 class MyFullDrawModifier extends DrawModifier { public scaleX: number 1; public scaleY: number 1; uiContext: UIContext; constructor(uiContext: UIContext) { super(); this.uiContext uiContext; } // 重载drawBehind方法自定义绘制背景 drawBehind(context: DrawContext): void { const brush new drawing.Brush(); brush.setColor({ alpha: 255, red: 255, green: 0, blue: 0 }); context.canvas.attachBrush(brush); const halfWidth context.size.width / 2; const halfHeight context.size.height / 2; context.canvas.drawRect({ left: this.uiContext.vp2px(halfWidth - 50 * this.scaleX), top: this.uiContext.vp2px(halfHeight - 50 * this.scaleY), right: this.uiContext.vp2px(halfWidth 50 * this.scaleX), bottom: this.uiContext.vp2px(halfHeight 50 * this.scaleY) }); } // 重载drawContent方法自定义绘制内容 drawContent(context: DrawContext): void { const brush new drawing.Brush(); brush.setColor({ alpha: 255, red: 0, green: 255, blue: 0 }); context.canvas.attachBrush(brush); const halfWidth context.size.width / 2; const halfHeight context.size.height / 2; context.canvas.drawRect({ left: this.uiContext.vp2px(halfWidth - 30 * this.scaleX), top: this.uiContext.vp2px(halfHeight - 30 * this.scaleY), right: this.uiContext.vp2px(halfWidth 30 * this.scaleX), bottom: this.uiContext.vp2px(halfHeight 30 * this.scaleY) }); } // 重载drawFront方法自定义绘制内容前景 drawFront(context: DrawContext): void { const brush new drawing.Brush(); brush.setColor({ alpha: 255, red: 0, green: 0, blue: 255 }); context.canvas.attachBrush(brush); const halfWidth context.size.width / 2; const halfHeight context.size.height / 2; const radiusScale (this.scaleX this.scaleY) / 2; context.canvas.drawCircle(this.uiContext.vp2px(halfWidth), this.uiContext.vp2px(halfHeight), this.uiContext.vp2px(20 * radiusScale)); } } // 继承DrawModifier实现自定义绘制控制器仅支持自定义绘制内容前景 class MyFrontDrawModifier extends DrawModifier { public scaleX: number 1; public scaleY: number 1; uiContext: UIContext; constructor(uiContext: UIContext) { super(); this.uiContext uiContext; } drawFront(context: DrawContext): void { const brush new drawing.Brush(); brush.setColor({ alpha: 255, red: 0, green: 0, blue: 255 }); context.canvas.attachBrush(brush); const halfWidth context.size.width / 2; const halfHeight context.size.height / 2; const radiusScale (this.scaleX this.scaleY) / 2; context.canvas.drawCircle(this.uiContext.vp2px(halfWidth), this.uiContext.vp2px(halfHeight), this.uiContext.vp2px(20 * radiusScale)); } } Entry Component struct DrawModifierExample { private fullModifier: MyFullDrawModifier new MyFullDrawModifier(this.getUIContext()); private frontModifier: MyFrontDrawModifier new MyFrontDrawModifier(this.getUIContext()); private drawAnimator: AnimatorResult | undefined undefined; State modifier: DrawModifier new MyFrontDrawModifier(this.getUIContext()); private count 0; // 创建Animator对象并设置动画 create() { let self this; this.drawAnimator this.getUIContext().createAnimator({ duration: 1000, easing: ease, delay: 0, fill: forwards, direction: normal, iterations: 1, begin: 0, end: 2 }); this.drawAnimator.onFrame (value: number) { console.info(frame value , value); const tempModifier self.modifier as MyFullDrawModifier | MyFrontDrawModifier; tempModifier.scaleX Math.abs(value - 1); tempModifier.scaleY Math.abs(value - 1); // 主动触发重绘 self.modifier.invalidate(); }; } build() { Column() { Row() { Text(test text) .width(100) .height(100) .margin(10) .backgroundColor(Color.Gray) .onClick(() { const tempModifier this.modifier as MyFullDrawModifier | MyFrontDrawModifier; tempModifier.scaleX - 0.1; tempModifier.scaleY - 0.1; }) .drawModifier(this.modifier) } Row() { Button(create) .width(100) .height(100) .borderRadius(50) .margin(10) .onClick(() { this.create(); }) Button(play) .width(100) .height(100) .borderRadius(50) .margin(10) .onClick(() { if (this.drawAnimator) { this.drawAnimator.play(); } }) Button(changeModifier) .width(100) .height(100) .borderRadius(50) .margin(10) .onClick(() { this.count 1; if (this.count % 2 1) { console.info(change to full modifier); this.modifier this.fullModifier; } else { console.info(change to front modifier); this.modifier this.frontModifier; } }) } } .width(100%) .height(100%) } }运行效果如图总结以下内容严格对应官方文档约束是保证DrawModifier正常运行的关键务必遵守UIContext获取规范必须通过组件实例的getUIContext()方法获取UI上下文禁止手动创建UIContext对象构造函数传入时确保上下文有效单位转换要求自定义绘制时必须通过uiContext.vp2px()将vp单位转为px单位适配不同屏幕密度避免不同设备显示尺寸异常主动重绘强制要求动态修改scaleX、scaleY等绘制参数后必须调用modifier.invalidate()方法否则组件不会重新绘制参数变更无效画笔资源管理绘制完成后无需手动detachBrush框架会自动管理画笔资源避免手动释放导致绘制异常动画初始化时机Animator对象仅需初始化一次多次点击create按钮会重复创建动画导致动画异常建议初始化后禁用按钮修饰器类型强转动态修改不同修饰器参数时需通过as关键字强转为对应自定义修饰器类型否则无法访问scaleX/scaleY自定义属性绘制层级冲突drawFront层级最高会覆盖组件所有内容避免绘制图形过大导致组件原有交互区域被遮挡如果这篇文章对你有帮助欢迎点赞、收藏、关注你的支持是持续创作的动力

相关新闻