鸿蒙全局安全水印组件实践:支持动态更新、全局生效、自定义样式
1、需求背景很多企业内部应用都会有这样的需求页面显示员工姓名、工号防止截图泄露全局统一水印动态切换水印内容不影响页面交互效果如下2、核心思路本方案采用纯 ArkUI 水印覆盖方案核心实现思路“砖墙式” 平铺效果angle属性倾斜HitTest 穿透不阻塞页面点击emitter全局动态刷新3、方案特点全屏水印层确保水印永远位于页面最上层所有页面都会被覆支持动态更新支持自定义样式不影响页面点击使用简单一次接入全 App 生效已封装为 npm 组件真正做到开箱即用性能稳定4、项目地址GitHubHarmonyWatermarkohpmericbyliang/lib_watermark5、使用方法5.1 安装组件安装 ohpm 包ohpm install ericbyliang/lib_watermark5.2 页面使用全局安全水印组件加入顶级根界面即可永远处于页面最上层import { setWatermarkText, WatermarkComponent } from ericbyliang/lib_watermark;build() { Root() { .... WatermarkComponent() } }5.3 全局设置水印文本import { setWatermarkText, WatermarkComponent } from ericbyliang/lib_watermark;// 设置水印比如登录后设置一次即可setWatermarkText(林俊杰 2000022);// 取消水印比如在登录页面setWatermarkText();这意味着登录后可以设置员工信息退出登录后可以清除用户切换账号可动态刷新5.4 动态设置水印文本自定义水印样式组件支持动态传参WatermarkComponent({ waterText:周杰伦 1000001, textSize: 14, textColor: rgba(80,80,80, 0.01), angle: -20, grapX: 120, grapY: 180 })支持参数参数说明waterText水印文本textSize字体大小rpxtextColor水印颜色/透明度angle旋转角度gapX水平间距gapY垂直间距6、核心代码讲解1、组件首先通过 emitter 监听全局水印事件实现登录后动态设置员工信息切换账号实时刷新退出登录清除水印2、构建一个且唯一的全屏透明覆盖层保证水印永远处于页面最上层import { emitter } from kit.BasicServicesKit; import { EventType } from ./EventType; Component export struct WatermarkComponent { Prop waterText?: string Prop textSize: number 14 Prop textColor: string rgba(80,80,80,0.08) Prop angle: number -20 Prop gapX: number 120 Prop gapY: number 180 aboutToAppear(): void { emitter.on(EventType.WaterMarkEvent, (eventData: emitter.EventData) { const waterText eventData?.data?.waterText as string //全局安全水印 this.waterText waterText }); } aboutToDisappear(): void { emitter.off(EventType.WaterMarkEvent) } build() { // 全屏水印层 Stack() { // 在这里放重复水印 if (this.waterText) { this.renderWatermark(); } } .width(100%) .height(100%) .align(Alignment.Center) .backgroundColor(Color.Transparent) .hitTestBehavior(HitTestMode.Transparent) // 穿透点击 .zIndex(9999); } // 绘制多个水印 Builder private renderWatermark() { Column() { ForEach(Array.from({ length: 100 }), (_: number, index: number) { Row() { ForEach(Array.from({ length: 30 }), () { Text(this.waterText) .fontSize(this.textSize) .fontColor(this.textColor) // 透明度 .padding({ right: this.gapX, bottom: this.gapY}) } ) }.rotate({ angle: this.angle, }).margin({left:index % 2 0?0:(this.textSize * (this.waterText||).length) / 2}) }) }.margin({top:-100}) } }