鸿蒙全局安全水印组件实践:支持动态更新、全局生效、自定义样式
摘要: 本文介绍了一个基于ArkUI的企业级动态水印解决方案,支持全屏覆盖、穿透点击和实时更新。方案通过WatermarkComponent组件实现砖墙式平铺水印,可动态设置员工姓名/工号,登录后全局生效,退出自动清除。组件支持自定义文本、大小、颜色、旋转角度及间距,通过emitter实现跨页面状态同步。核心代码采用透明堆叠层(zIndex:9999)确保水印置顶,结合HitTestBehavio
1、需求背景
很多企业内部应用,都会有这样的需求:
- 页面显示员工姓名、工号
- 防止截图泄露
- 全局统一水印
- 动态切换水印内容
- 不影响页面交互
效果如下:

2、核心思路
本方案采用 纯 ArkUI 水印覆盖方案,核心实现思路:
- “砖墙式” 平铺效果
- angle属性倾斜
- HitTest 穿透,不阻塞页面点击
- emitter全局动态刷新
3、方案特点
- 全屏水印层,确保水印永远位于页面最上层,所有页面都会被覆
- 支持动态更新
- 支持自定义样式
- 不影响页面点击
- 使用简单,一次接入,全 App 生效
- 已封装为 npm 组件,真正做到开箱即用
- 性能稳定
4、项目地址
GitHub:HarmonyWatermark
ohpm:@ericbyliang/lib_watermark
5、使用方法
5.1 安装组件
安装 ohpm 包:
ohpm install @ericbyliang/lib_watermark
5.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 |
字体大小(rpx) |
|
textColor |
水印颜色/透明度 |
|
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})
}
}
更多推荐



所有评论(0)