- 前端
- UI组件
- 设计系统
【免费下载链接】ant-design-vue
🌈 An enterprise-class UI components based on Ant Design and Vue. 🐜
水印(Watermark)是 ant-design-vue 提供的“其他(Other)”类型组件之一,用于在页面或指定容器上叠加版权标识文字或图案,是防止信息盗用、声明版权的常用手段。本文以 components/watermark/index.en-US.md 的官方 API 为骨架,结合该组件在仓库中的 TypeScript 源码、工具函数 与 官方示例,系统讲解每一个配置参数的实际效果与底层实现,帮助你快速上手并在生产环境中精确掌控水印的尺寸、间距、旋转与字体表现。
何时使用水印
根据官方文档,在以下两种典型场景中应当使用 Watermark 组件:
- 版权声明:页面需要添加水印来标识内容归属方或版权信息,例如内部系统、预览页面、资料分享页面。
- 防信息盗用:在包含敏感信息的页面上叠加水印,即使页面被截图或录屏,也能追溯到来源,起到威慑与溯源作用。
从 组件入口 的实现看,Watermark 渲染为一个position: relative的容器节点(默认插槽承载业务内容),水印层则作为容器内的一个position: absolute子元素平铺在整个区域上,且设置了pointer-events: none(源码位置),因此水印不会拦截用户的任何鼠标操作,可以安全地包裹表格、表单、富文本等交互组件。
快速上手:一行代码生成基础水印
最简单的用法是给容器包裹一层<a-watermark>并传入content文字内容。参考 basic.vue 示例:
<template> <a-watermark content="Ant Design Vue"> <div style="height: 500px" /> </a-watermark> </template>content为水印文字,未显式指定width/height时,水印块尺寸会根据文字内容自动计算(详见下文“实现原理”小节)。组件会在挂载后(onMounted)自动完成水印绘制,无需额外初始化代码。
Watermark API 全参数详解
官方 API 定义了 9 个配置属性,下表完整继承自 index.en-US.md:
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| width | 水印的宽度,content的默认值为自身的宽度 | number | 120 |
| height | 水印的高度,content的默认值为自身的高度 | number | 64 |
| rotate | 水印绘制时,旋转的角度,单位° | number | -22 |
| zIndex | 追加的水印元素的 z-index | number | 9 |
| image | 图片源,建议导出 2 倍或 3 倍图,优先级高 | string | - |
| content | 水印文字内容 | string | string[] | - |
| font | 文字样式 | Font | Font |
| gap | 水印之间的间距 | [number, number] | [100, 100] |
| offset | 水印距离容器左上角的偏移量,默认为gap/2 | [number, number] | [gap[0]/2, gap[1]/2] |
以上默认值在 index.tsx 的 initDefaultProps 中声明(zIndex: 9、rotate: -22、gap: [100, 100]),并在 computed 属性 中进一步处理。下面逐个深入解读。
width / height:水印块尺寸
- 单位为像素,定义单个水印内容块的宽高,决定 Canvas 绘制区域与平铺密度。
- 当使用
content文字水印且未显式指定时,宽高由文字自动测算:宽度取所有行measureText的最大宽度,高度为fontSize * 行数 + 行间空隙(见 getMarkSize 实现)。 - 当使用
image图片水印时,默认值为120 × 64。官方示例建议显式设置 width 和 height,并上传至少两倍宽高的 logo 图片,以保证图片高清且不被拉伸,参见 image.vue 示例:
<template> <a-watermark :height="30" :width="130" image="https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*lkAoRbywo0oAAAAAAAAAAAAADrJ8AQ/original" > <div style="height: 500px" /> </a-watermark> </template>提示:示例中的图片地址为官方演示资源,生产环境中请替换为你自己的 logo 或图案资源。
rotate:旋转角度
水印绘制时的旋转角度,单位为度(°),默认-22,即逆时针倾斜 22 度。旋转以水印块的中心点为轴进行,对应的几何变换封装在 rotateWatermark 中:
ctx.translate(rotateX, rotateY); ctx.rotate((Math.PI / 180) * Number(rotate)); ctx.translate(-rotateX, -rotateY);custom.vue 示例 允许在-180 ~ 180范围内实时调节该值预览效果。
zIndex:层级控制
水印 DOM 元素的 z-index,默认9。该值决定了水印在容器内的叠放顺序。在 custom.vue 示例 中,示例图片设置了z-index: 10以盖在水印之上,直观演示了层级关系。请根据页面实际内容层级调整该值。
image:图片水印(优先级高于 content)
- 图片源地址(string),官方建议导出2x 或 3x 倍图以保证高 DPI 屏幕下清晰。
- 优先级最高:源码中
renderWatermark首先判断image,若设置了图片则走图片分支,忽略content文字(见 index.tsx 的分支逻辑)。 - 加载细节:图片通过
img.onload异步加载完成后才把水印toDataURL()写入背景,并设置了img.crossOrigin = 'anonymous'与img.referrerPolicy = 'no-referrer',用于规避跨域 Canvas 污染问题(源码位置)。
content:多行文字水印
- 类型为
string | string[]。传入字符串数组即可渲染多行水印,参考 multi-line.vue 示例:
<template> <a-watermark :content="['Ant Design Vue', 'Happy Working']"> <div style="height: 500px" /> </a-watermark> </template>- 多行文本在 fillTexts 中逐行绘制,行与行之间按
FontGap(常量 3,经像素比缩放)间隔排列;同时每行文本以textAlign: 'center'、textBaseline: 'top'对齐,保证整体居中。
gap:水印间距
- 类型为
[number, number],分别表示水平方向(gapX)与垂直方向(gapY)相邻水印的间距,默认[100, 100]。 - 在源码中通过
gapX = props.gap?.[0] ?? 100与gapY = props.gap?.[1] ?? 100读取(index.tsx#L50-L51),它直接决定了 Canvas 画布尺寸((gap + markWidth) * ratio)与水印平铺密度。 - 注意:gap 的取值必须大于单个水印块的尺寸,否则水印会相互覆盖、密集叠加,影响可读性。
offset:水印偏移
- 类型为
[number, number],表示水印距离容器左上角的偏移量,默认值为gap[0]/2, gap[1]/2(源码见 index.tsx#L52-L55)。 - 偏移量的实现方式是调整水印层 DOM 的
left/top与backgroundPosition:当偏移为正值时,容器水印区域相应收缩(width: calc(100% - left)),从而让平铺的水印整体向右下位移,见 markStyle 计算。 - 在 custom.vue 示例 中,可以通过两个
a-input-number分别调节水平/垂直偏移实时预览。
Font 字体样式详解
font属性为水印文字提供完整的字体控制,其子属性与默认值如下表(继承自 index.en-US.md):
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| color | 字体颜色 | string | rgba(0,0,0,.15) |
| fontSize | 字体大小 | number | 16 |
| fontWeight | 字体粗细 | normal|light|weight| number | normal |
| fontFamily | 字体类型 | string | sans-serif |
| fontStyle | 字体样式 | none|normal|italic|oblique | normal |
使用方式(参见 custom.vue 中font.fontSize的调节逻辑):
<template> <a-watermark :font="{ color: 'rgba(0,0,0,.15)', fontSize: 16, fontWeight: 'normal', fontFamily: 'sans-serif', fontStyle: 'normal' }"> <div style="height: 500px" /> </a-watermark> </template>源码级补充(来自 index.tsx 的字体处理):
fontSize与color的默认值并非硬编码,而是从主题 Token读取:字体大小默认取token.fontSizeLG(即大号字体尺寸,通常为 16),颜色默认取token.colorFill(即rgba(0,0,0,.15)),因此会跟随 ConfigProvider 主题自动变化;当显式传入font.fontSize/font.color时则优先使用自定义值。fontWeight支持'normal' | 'light' | 'weight'或数字(如 500、700);fontStyle支持'none' | 'normal' | 'italic' | 'oblique'。- 字体最终拼接为完整的 Canvas
ctx.font字符串:${fontStyle} normal ${fontWeight} ${fontSize}px/${lineHeight}px ${fontFamily}(见 fillTexts)。
组件实现原理:Canvas 绘制 + 交错平铺 + 防篡改重绘
深入源码可以发现,Watermark 并不是简单的 CSS 平铺,而是完整的 Canvas 渲染管线,主要分三部分:
1. Canvas 绘制水印单元。renderWatermark(index.tsx#L155-L210)动态创建<canvas>,按照devicePixelRatio(见 getPixelRatio)放大绘制以保证高分屏清晰度,绘制完成后通过canvas.toDataURL()生成 base64 图片,写入水印层 DIV 的backgroundImage,并以backgroundRepeat: 'repeat'平铺。
2. 双单元交错布局。源码顶部定义常量BaseSize = 2(index.tsx#L13),画布横向/纵向均放大 2 倍,并在原单元的基础上额外绘制一组旋转后的“交错单元”(alternateDrawX/alternateDrawY,见 index.tsx#L179-L207),使水印呈棋盘式交错排列、铺满不留白。注释也明确指出:当前仅支持“交错布局(alternate layout)”这一种平铺模式。
3. MutationObserver 防篡改。组件通过 useMutationObserver 监听容器节点的style/class属性变化与子节点增删(index.tsx#L238-L243),一旦检测到水印节点被删除或属性被修改(判定逻辑见 reRendering),立即重新销毁并渲染水印,抵御用户通过 DevTools 手动移除水印的常见做法。内部更新时则通过stopObservation标志短暂暂停监听(index.tsx#L99-L112),避免自触发重绘循环。
4. 响应式重绘。组件通过watch深度监听 props 与主题 Token(token.colorFill、token.fontSizeLG)变化(index.tsx#L214-L223),配置或主题变更后自动重新绘制;组件卸载时调用destroyWatermark清理水印节点(index.tsx#L224-L226)。
该组件的挂载、渲染与快照行为在 watermark 单元测试 中有覆盖:测试挂载了带content="Ant Design"的 Watermark 并断言.watermark节点存在且输出快照一致,可作为二次开发时验证组件行为的参考。
注意事项与最佳实践
- 包裹容器必须可被定位:水印层使用绝对定位平铺在容器内,请将水印应用于有实际尺寸的内容块上;示例中常以
height: 500px的占位 div 演示,实际项目中直接包裹表格、卡片等真实内容即可。 - image 与 content 二选一:同时设置时
image优先,content不会渲染;如需两者并存,请考虑使用多行文字配合图片的两套组件或自行扩展。 - 图片水印务必显式设置宽高:为保证高清且不变形,官方建议 width/height 与图片实际宽高比例一致,并上传 2 倍或 3 倍图。
- 合理控制层级:默认
zIndex: 9通常足以覆盖内容,若页面内存在更高层级的浮层(如弹窗、抽屉),请相应调高 zIndex 或在水印容器外继续包裹。 - gap 应大于水印尺寸:间距过小会导致水印重叠密集,建议以
gap ≥ width/height为起点调节,可通过 custom.vue 示例 的滑块与输入框直观体验各参数的联动效果。
- 前端
- UI组件
- 设计系统
【免费下载链接】ant-design-vue
🌈 An enterprise-class UI components based on Ant Design and Vue. 🐜
相关推荐
Element Plus Watermark 水印组件完全指南:从基础用法到 Canvas 渲染原理
Element Plus Watermark 水印组件完全指南:从基础用法到 Canvas 渲染原理 <el watermark 是 Element Plus
前端UI组件Vant 4 Watermark 水印组件完整指南:用法、API 与 SVG 渲染原理
Vant 4 Watermark 水印组件完整指南:用法、API 与 SVG 渲染原理 导读 本文围绕 Vant 4 的 Watermark 水印组件展开,讲解
前端UI组件ant-design-vue QRCode 组件完全指南:从 API 配置到源码级实现原理
ant design vue QRCode 组件完全指南:从 API 配置到源码级实现原理 本指南以 ant design vue 仓库中的 QRCode 官方
前端UI组件设计系统
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考