invisible-watermark-vue
v1.0.0
Published
A TypeScript library for creating and detecting invisible watermarks using Canvas API, with Vue 3 support
Maintainers
Readme
Invisible Watermark Vue
一个基于 Canvas 的隐形水印 TypeScript 库,专为 Vue 3 优化,支持创建不可见的文本水印用于追踪和版权保护。
特性
- 🎯 Vue 指令 - 提供
v-watermark指令,使用超级简单 - ⚡️ 组合式 API - 完整的 Vue 3 Composition API 支持
- 🔒 隐形水印 - 使用极低透明度的文本创建肉眼几乎不可见的水印
- 📸 截图追踪 - 水印在截图中保留,可用于追踪泄密源头
- 🎨 灵活配置 - 自定义透明度、字体、旋转角度、间距等
- 🎯 TypeScript - 完整的类型定义支持
- 📦 轻量级 - 核心库仅 ~3.5KB (gzipped 1.35KB)
- 🛡️ 代码混淆 - 生产代码经过混淆压缩,增加安全性
安装
# 使用 npm
npm install invisible-watermark-vue
# 使用 pnpm
pnpm add invisible-watermark-vue
# 使用 yarn
yarn add invisible-watermark-vue快速开始
方式一:Vue 指令(最简单 ⭐推荐)
1. 注册插件
// main.ts
import { createApp } from 'vue';
import { WatermarkPlugin } from 'invisible-watermark-vue';
import App from './App.vue';
const app = createApp(App);
app.use(WatermarkPlugin); // 全局注册 v-watermark 指令
app.mount('#app');2. 使用指令
<template>
<!-- 对象语法:完整配置 -->
<div v-watermark="{ text: 'user_12345', opacity: 0.005 }" class="content">
这是受保护的内容区域
</div>
<!-- 字符串简写:仅设置文本 -->
<div v-watermark="'user_12345'" class="content">
快速添加水印
</div>
<!-- 响应式:动态更新 -->
<div v-watermark="watermarkConfig" class="content">
响应式水印
</div>
</template>
<script setup lang="ts">
import { reactive } from 'vue';
const watermarkConfig = reactive({
text: 'user_' + Date.now(),
opacity: 0.005,
fontSize: 20,
rotate: -15,
});
// 修改 watermarkConfig 会自动更新水印
function updateWatermark() {
watermarkConfig.text = 'new_user_id';
watermarkConfig.opacity = 0.01;
}
</script>3. 局部注册(可选)
如果不想全局注册,也可以在组件中局部注册:
<script setup lang="ts">
import { vWatermark } from 'invisible-watermark-vue';
// 在 <script setup> 中,指令会自动可用
</script>
<template>
<div v-watermark="'user_12345'">内容</div>
</template>或使用 Options API:
<script>
import { vWatermark } from 'invisible-watermark-vue';
export default {
directives: {
watermark: vWatermark,
},
};
</script>方式二:组合式 API
如果需要更多控制,可以使用 useWatermark 组合式函数:
<template>
<div>
<div ref="containerRef" class="content">
受保护的内容区域
</div>
<button @click="apply({ text: 'user_12345', opacity: 0.005 })">
应用水印
</button>
<button @click="update({ opacity: 0.01 })">更新水印</button>
<button @click="clear">清除水印</button>
<p v-if="isApplied">当前水印: {{ currentText }}</p>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { useWatermark } from 'invisible-watermark-vue';
const containerRef = ref<HTMLElement | null>(null);
const { isApplied, currentText, apply, update, clear, destroy } = useWatermark(
containerRef,
// 可选:组件挂载时自动应用
{
text: 'user_12345',
opacity: 0.005,
}
);
</script>方式三:原生 JavaScript/TypeScript
如果不使用 Vue,也可以直接使用核心类:
import { WatermarkCreator } from 'invisible-watermark-vue';
const creator = new WatermarkCreator();
const container = document.getElementById('content')!;
// 应用水印
creator.apply(container, {
text: 'user_12345',
opacity: 0.005,
fontSize: 20,
rotate: -15,
});
// 更新水印
creator.update({ text: 'user_67890' });
// 启用窗口大小变化时自动重绘
const cleanup = creator.enableAutoResize();
// 清除水印
creator.clear();
// 销毁水印
creator.destroy();
cleanup(); // 清理事件监听器API 文档
v-watermark 指令
<!-- 对象语法 -->
<div v-watermark="WatermarkOptions">...</div>
<!-- 字符串简写(仅文本) -->
<div v-watermark="string">...</div>特性:
- ✅ 自动生命周期管理(mounted/updated/unmounted)
- ✅ 响应式更新
- ✅ 自动调整窗口大小
- ✅ 条件渲染支持(v-if/v-show)
WatermarkPlugin
Vue 插件,用于全局注册 v-watermark 指令。
import { WatermarkPlugin } from 'invisible-watermark-vue';
app.use(WatermarkPlugin);useWatermark (组合式函数)
function useWatermark(
containerRef: Ref<HTMLElement | null>,
options?: WatermarkOptions
): {
isApplied: Ref<boolean>; // 水印是否已应用
currentText: Ref<string>; // 当前水印文本
apply: (options?: WatermarkOptions) => void; // 应用水印
update: (options: Partial<WatermarkOptions>) => void; // 更新水印
clear: () => void; // 清除水印
destroy: () => void; // 销毁水印
}WatermarkCreator (核心类)
方法
apply(container: HTMLElement, options: WatermarkOptions)- 应用水印到指定容器update(options: Partial<WatermarkOptions>)- 更新水印配置clear()- 清除水印内容destroy()- 销毁水印(移除Canvas元素)enableAutoResize()- 启用窗口大小变化时自动重绘,返回清理函数getCurrentText()- 获取当前水印文本getCurrentOptions()- 获取当前配置
WatermarkOptions (配置选项)
interface WatermarkOptions {
text: string; // 水印文本内容(必填)
opacity?: number; // 透明度 0-1,默认 0.005
fontSize?: number; // 字体大小,默认 20
fontFamily?: string; // 字体样式,默认 'Arial'
rotate?: number; // 旋转角度(度),默认 -15
color?: string; // RGB格式颜色,默认 '0, 0, 0'
spacingX?: number; // 水平间距倍数,默认 1
spacingY?: number; // 垂直间距倍数,默认 1.5
}配置说明:
- text: 必填,水印文本,建议使用用户ID、时间戳等唯一标识
- opacity: 透明度,0.005 推荐(肉眼几乎不可见),0.01 稍微可见但更容易追踪
- fontSize: 字体大小,影响水印密度
- fontFamily: 字体,建议使用系统通用字体
- rotate: 旋转角度,-15° 是常用值,增加隐蔽性
- color: RGB颜色值,默认黑色
- spacingX/Y: 控制水印间距,值越大间距越大
使用示例
示例 1:保护敏感页面
<template>
<div v-watermark="userWatermark" class="sensitive-page">
<h1>机密文档</h1>
<p>这里是敏感内容...</p>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import { useUserStore } from '@/stores/user';
const userStore = useUserStore();
const userWatermark = computed(() => ({
text: `${userStore.username}_${userStore.userId}_${Date.now()}`,
opacity: 0.005,
fontSize: 18,
}));
</script>示例 2:数据可视化保护
<template>
<div v-watermark="chartWatermark" class="chart-container">
<ECharts :option="chartOption" />
</div>
</template>
<script setup lang="ts">
const chartWatermark = {
text: 'Company Internal Data',
opacity: 0.003,
fontSize: 24,
rotate: -20,
spacingX: 1.5,
spacingY: 2,
};
</script>示例 3:条件渲染
<template>
<div
v-if="isInternalUser"
v-watermark="`internal_${userId}`"
class="content">
内部用户专属内容
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const isInternalUser = ref(true);
const userId = ref('12345');
</script>工作原理
水印创建
- 在目标容器上创建一个透明覆盖层 Canvas 元素
- 使用极低透明度(如 0.005)的文本在 Canvas 上重复绘制
- 文本以网格形式铺满整个区域,并旋转一定角度增加隐蔽性
- 肉眼几乎无法察觉,但截图后依然保留在图像中
- 支持高DPI屏幕,自动处理设备像素比
特性
- ✅ 自动处理容器定位(如果是static会自动改为relative)
- ✅ 支持窗口大小变化时自动重绘
- ✅ 高DPI屏幕适配
- ✅ 不影响页面交互(pointer-events: none)
- ✅ 可动态更新水印内容
- ✅ 组件卸载时自动清理
使用场景
- 🔐 内部文档溯源 - 追踪文档泄露源头
- 📄 防截图泄密 - 在敏感内容页面添加用户标识
- 👤 用户行为追踪 - 记录用户访问痕迹
- 📊 数据可视化保护 - 保护图表和数据展示
- 💼 企业内容管理 - 标记内部文件和报告
注意事项
透明度设置建议
| 透明度 | 可见度 | 追踪能力 | 适用场景 | |--------|--------|----------|----------| | 0.003 | 几乎完全不可见 | 低(压缩后可能丢失) | 极度敏感内容 | | 0.005 | 肉眼基本不可见 | 中等 | 推荐,一般使用 | | 0.01 | 细看可能察觉 | 高 | 需要强追踪能力 |
最佳实践
- 截图格式: 建议使用 PNG 格式,JPG 压缩可能损失水印
- 水印文本: 使用唯一标识符(用户ID、时间戳、会话ID等)
- 后端记录: 配合后端记录"用户→水印文本"映射,便于追溯
- 多层防护: 结合其他安全措施(访问控制、日志记录等)
兼容性
- ✅ 现代浏览器(支持 Canvas API)
- ✅ Vue 3.x
- ✅ TypeScript 5.x
- ✅ 支持 ESM 和 CommonJS
开发
# 安装依赖
pnpm install
# 开发模式(监听文件变化)
pnpm run dev
# 构建(包含代码混淆)
pnpm run build构建产物
dist/index.js- ESM 格式(混淆压缩)dist/index.cjs- CommonJS 格式(混淆压缩)dist/index.d.ts- TypeScript 类型定义dist/index.d.cts- CommonJS TypeScript 类型定义- 包含 Source Maps
License
MIT
贡献
欢迎提交 Issue 和 Pull Request!
