npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

invisible-watermark-vue

v1.0.0

Published

A TypeScript library for creating and detecting invisible watermarks using Canvas API, with Vue 3 support

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>

工作原理

水印创建

  1. 在目标容器上创建一个透明覆盖层 Canvas 元素
  2. 使用极低透明度(如 0.005)的文本在 Canvas 上重复绘制
  3. 文本以网格形式铺满整个区域,并旋转一定角度增加隐蔽性
  4. 肉眼几乎无法察觉,但截图后依然保留在图像中
  5. 支持高DPI屏幕,自动处理设备像素比

特性

  • ✅ 自动处理容器定位(如果是static会自动改为relative)
  • ✅ 支持窗口大小变化时自动重绘
  • ✅ 高DPI屏幕适配
  • ✅ 不影响页面交互(pointer-events: none)
  • ✅ 可动态更新水印内容
  • ✅ 组件卸载时自动清理

使用场景

  • 🔐 内部文档溯源 - 追踪文档泄露源头
  • 📄 防截图泄密 - 在敏感内容页面添加用户标识
  • 👤 用户行为追踪 - 记录用户访问痕迹
  • 📊 数据可视化保护 - 保护图表和数据展示
  • 💼 企业内容管理 - 标记内部文件和报告

注意事项

透明度设置建议

| 透明度 | 可见度 | 追踪能力 | 适用场景 | |--------|--------|----------|----------| | 0.003 | 几乎完全不可见 | 低(压缩后可能丢失) | 极度敏感内容 | | 0.005 | 肉眼基本不可见 | 中等 | 推荐,一般使用 | | 0.01 | 细看可能察觉 | 高 | 需要强追踪能力 |

最佳实践

  1. 截图格式: 建议使用 PNG 格式,JPG 压缩可能损失水印
  2. 水印文本: 使用唯一标识符(用户ID、时间戳、会话ID等)
  3. 后端记录: 配合后端记录"用户→水印文本"映射,便于追溯
  4. 多层防护: 结合其他安全措施(访问控制、日志记录等)

兼容性

  • ✅ 现代浏览器(支持 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!