Skip to content

v-watermarker

介绍

v-watermarker 指令用于在元素上添加水印效果,以保护内容的版权或标识。对于图片元素,水印会直接与图片内容合并,防止通过控制台查看原始图片。

基础用法

在图片上应用基本水印:

点击查看代码
vue
<template>
  <div class="demo-container">
    <div class="watermark-box">
      <img
        v-watermarker="{
          text: '基础水印',
          fontSize: 30,
          opacity: 0.4,
          gap: 200
        }"
        src="https://images.unsplash.com/photo-1579353977828-2a4eab540b9a?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=80"
        alt="风景图片"
        class="demo-image"
      />
    </div>
    <div class="description">
      <p>基础水印示例 - 使用默认对角线方向,调整了透明度和间距</p>
    </div>
  </div>
</template>

<script setup>
import { vWatermarker } from '@cp-vuedir/core'
</script>

<style scoped>
.demo-container {
  border: 1px solid var(--vp-c-divider);
  border-radius: 8px;
  padding: 20px;
  margin-bottom: 20px;
}

.watermark-box {
  width: 100%;
  border: 1px solid var(--vp-c-divider);
  border-radius: 4px;
  position: relative;
  margin-bottom: 10px;
  height: 400px;
}

.demo-image {
  width: 100%;
  height: 100%;
}

.description {
  font-size: 14px;
  color: var(--vp-c-text-2);
  margin-top: 10px;
  text-align: center;
}
</style>

水印方向

水印支持三种方向:水平、垂直和对角线:

点击查看代码
vue
<template>
  <div class="demo-container">
    <div class="direction-demos">
      <div class="watermark-box">
        <img
          v-watermarker="{
            text: '水平方向',
            direction: 'horizontal',
            fontSize: 24,
            opacity: 0.5,
            textColor: '#0066cc',
            gap: 70
          }"
          src="https://images.unsplash.com/photo-1506744038136-46273834b3fb?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=80"
          alt="山水风景"
          class="demo-image"
        />
        <div class="label">水平方向</div>
      </div>

      <div class="watermark-box">
        <img
          v-watermarker="{
            text: '垂直方向',
            direction: 'vertical',
            fontSize: 24,
            opacity: 0.5,
            textColor: '#cc3300',
            gap: 70
          }"
          src="https://images.unsplash.com/photo-1472214103451-9374bd1c798e?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=80"
          alt="田野风景"
          class="demo-image"
        />
        <div class="label">垂直方向</div>
      </div>

      <div class="watermark-box">
        <img
          v-watermarker="{
            text: '对角线方向',
            direction: 'diagonal',
            fontSize: 24,
            opacity: 0.5,
            textColor: '#006633',
            gap: 70
          }"
          src="https://images.unsplash.com/photo-1501785888041-af3ef285b470?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=80"
          alt="海岸风景"
          class="demo-image"
        />
        <div class="label">对角线方向</div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { vWatermarker } from '@cp-vuedir/core'
</script>

<style scoped>
.demo-container {
  border: 1px solid var(--vp-c-divider);
  border-radius: 8px;
  padding: 20px;
  margin-bottom: 20px;
}

.watermark-box {
  width: 100%;
  height: 250px;
  border: 1px solid var(--vp-c-divider);
  border-radius: 4px;
  overflow: hidden;
  position: relative;
  margin-bottom: 10px;
}

.demo-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.label {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  background-color: rgba(0, 0, 0, 0.6);
  color: white;
  padding: 8px;
  text-align: center;
  font-size: 14px;
  font-weight: bold;
}

.direction-demos {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 15px;
}

@media (max-width: 640px) {
  .direction-demos {
    grid-template-columns: 1fr;
  }
}
</style>

自定义样式

通过调整下面的控制面板,您可以实时体验不同水印参数的效果:

点击查看代码
vue
<template>
  <div class="demo-container">
    <div class="watermark-box">
      <img
        v-watermarker="{
          text: 'VueDir',
          fontSize: 28,
          fontFamily: 'Georgia, serif',
          textColor: '#ff3300',
          opacity: 0.4,
          gap: 100
        }"
        src="https://images.unsplash.com/photo-1552083375-1447ce886485?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=80"
        alt="城市风景"
        class="demo-image"
      />
    </div>
    <div class="description">
      <p>自定义样式示例 - 使用更大字体、特殊字体族和醒目的红色</p>
      <div class="style-info">
        <div class="style-item">
          <span class="label">字体大小:</span>
          <span class="value">28px</span>
        </div>
        <div class="style-item">
          <span class="label">字体族:</span>
          <span class="value">Georgia, serif</span>
        </div>
        <div class="style-item">
          <span class="label">文字颜色:</span>
          <span class="value"><span class="color-box"></span>#ff3300 </span>
        </div>
        <div class="style-item">
          <span class="label">透明度:</span>
          <span class="value">0.4</span>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { vWatermarker } from '@cp-vuedir/core'
</script>

<style scoped>
.demo-container {
  border: 1px solid var(--vp-c-divider);
  border-radius: 8px;
  padding: 20px;
  margin-bottom: 20px;
}

.watermark-box {
  width: 100%;
  height: 400px;
  border: 1px solid var(--vp-c-divider);
  border-radius: 4px;
  overflow: hidden;
  position: relative;
  margin-bottom: 15px;
}

.demo-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.description {
  font-size: 14px;
  color: var(--vp-c-text-2);
  margin-top: 10px;
  text-align: center;
}

.style-info {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 15px;
  margin-top: 10px;
}

.style-item {
  display: flex;
  align-items: center;
  gap: 5px;
}

.label {
  font-weight: bold;
  color: var(--vp-c-text-1);
}

.value {
  color: var(--vp-c-text-2);
}

.color-box {
  display: inline-block;
  width: 16px;
  height: 16px;
  background-color: #ff3300;
  border-radius: 3px;
  vertical-align: middle;
  margin-left: 5px;
}
</style>

交互式演示

上面的演示允许您调整以下参数:

  • 水印文本:自定义显示的文字内容
  • 水印方向:水平、垂直或对角线方向
  • 字体大小:调整文字的大小
  • 字体族:选择不同的字体样式
  • 文字颜色:使用颜色选择器更改颜色
  • 透明度:调整水印的透明度
  • 间距:调整水印之间的距离

远程图片水印

对远程图片应用水印(需要图片服务器支持跨域):

点击查看代码
vue
<template>
  <div class="demo-container">
    <div class="watermark-box">
      <img
        v-watermarker="{
          text: '远程图片水印',
          fontSize: 24,
          opacity: 0.4,
          direction: 'diagonal',
          textColor: '#0033cc',
          gap: 90
        }"
        src="https://images.unsplash.com/photo-1682687220063-4742bd7fd538?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=80"
        alt="远程图片"
        class="demo-image"
      />
    </div>
    <div class="description">
      <div class="title">远程图片水印示例</div>
      <p>此示例展示了对远程图片应用水印。水印会直接与图片内容合并,防止通过控制台查看原始图片。</p>
      <p class="note">注意:对于跨域图片,需要确保图片服务器允许跨域访问,否则可能无法正确应用水印。</p>
    </div>
  </div>
</template>

<script setup>
import { vWatermarker } from '@cp-vuedir/core'
</script>

<style scoped>
.demo-container {
  border: 1px solid var(--vp-c-divider);
  border-radius: 8px;
  padding: 20px;
  margin-bottom: 20px;
}

.watermark-box {
  width: 100%;
  height: 400px;
  border: 1px solid var(--vp-c-divider);
  border-radius: 4px;
  overflow: hidden;
  position: relative;
  margin-bottom: 15px;
}

.demo-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.description {
  font-size: 14px;
  color: var(--vp-c-text-2);
  line-height: 1.5;
  padding: 0 10px;
}

.title {
  font-weight: bold;
  font-size: 16px;
  color: var(--vp-c-text-1);
  margin-bottom: 8px;
  text-align: center;
}

.note {
  margin-top: 8px;
  font-style: italic;
  color: var(--vp-c-warning-1);
  padding: 8px;
  background-color: var(--vp-c-warning-soft);
  border-radius: 4px;
  border-left: 3px solid var(--vp-c-warning-1);
}
</style>

容器水印

对非图片元素应用水印:

点击查看代码
vue
<template>
  <div class="demo-container">
    <div
      v-watermarker="{
        text: '容器水印',
        fontSize: 20,
        opacity: 0.25,
        textColor: '#333333',
        gap: 80
      }"
      class="watermark-box container-demo"
    >
      <div class="content">
        <h3>容器水印示例</h3>
        <p>这是一个应用了水印的容器元素</p>
        <p>水印会覆盖在容器内容上方</p>
        <p>但不会影响容器内容的交互</p>
      </div>
    </div>
    <div class="description">
      <p>对于非图片元素,水印会作为一个覆盖层添加到元素上方,不会影响元素内容的交互。</p>
    </div>
  </div>
</template>

<script setup>
import { vWatermarker } from '@cp-vuedir/core'
</script>

<style scoped>
.demo-container {
  border: 1px solid var(--vp-c-divider);
  border-radius: 8px;
  padding: 20px;
  margin-bottom: 20px;
}

.watermark-box {
  width: 100%;
  height: 400px;
  border: 1px solid var(--vp-c-divider);
  border-radius: 4px;
  overflow: hidden;
  position: relative;
  margin-bottom: 15px;
}

.container-demo {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  background-color: var(--vp-c-bg-soft);
  padding: 20px;
}

.content {
  text-align: center;
  z-index: 1;
}

.content h3 {
  margin-bottom: 15px;
  font-size: 18px;
  color: var(--vp-c-text-1);
}

.content p {
  margin: 10px 0;
  font-size: 16px;
  color: var(--vp-c-text-1);
}

.demo-button {
  margin-top: 15px;
  padding: 8px 16px;
  background-color: var(--vp-c-brand);
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  transition: background-color 0.3s;
}

.demo-button:hover {
  background-color: var(--vp-c-brand-dark);
}

.description {
  font-size: 14px;
  color: var(--vp-c-text-2);
  margin-top: 10px;
  text-align: center;
}
</style>

功能特点

  • 图片水印保护:当应用于 <img> 标签时,会将图片转换为 Canvas 元素,并将水印直接绘制到图片上,防止用户通过控制台查看原始图片
  • 容器水印:当应用于非图片元素时,会在元素上方添加一个带有水印的层

使用示例

图片水印

html
<!-- 直接在图片上应用水印 -->
<img v-watermarker="{ text: '水印文本' }" src="/path/to/image.jpg" alt="图片描述" />

<!-- 自定义水印样式 -->
<img
  v-watermarker="{
    text: '公司名称',
    direction: 'diagonal',
    fontSize: 20,
    opacity: 0.2
  }"
  src="/path/to/image.jpg"
  alt="图片描述"
/>

容器水印

html
<!-- 在容器元素上应用水印 -->
<div v-watermarker="{ text: '水印文本' }" class="container">
  <!-- 容器内容 -->
</div>

SSR 兼容性注意事项

由于水印指令使用了浏览器 API(如 document、Canvas 等),在服务端渲染环境中需要使用 <ClientOnly> 组件包装使用该指令的组件:

html
<ClientOnly>
  <div v-watermarker="{ text: '水印文本' }">
    <!-- 内容 -->
  </div>
</ClientOnly>

或者使用条件导入方式:

js
if (!import.meta.env.SSR) {
  // 导入和使用水印指令
}

API

属性名说明类型是否必选默认值
text
水印文本内容
string
水印文本
direction
水印方向,可选值:'horizontal'(水平)/'vertical'(垂直)/ 'diagonal'(对角线)
string
diagonal
fontSize
字体大小
number
16
fontFamily
字体族
string
AaArial
textColor
文字颜色
string
#000000
opacity
透明度
number
0.1
gap
水印之间的间距
number
100
zIndex
水印层级(仅对非图片元素有效)
number
1000

注意事项

使用限制

  • 对于图片元素,水印会将 <img> 标签替换为 <canvas> 元素
  • 确保容器元素具有明确的宽高,否则水印可能无法正确显示
  • 水印会自动适应容器大小
  • 对于非图片元素,水印层的 pointer-events 设置为 none,不会影响容器内容的交互

跨域图片

对于远程图片,如果图片服务器没有设置正确的 CORS 头(Cross-Origin Resource Sharing),可能会导致无法正确应用水印。在这种情况下,Canvas 会被污染(tainted),无法读取或修改图片数据。

安全与性能

  • 图片水印通过 Canvas 直接合并图片和水印,防止用户通过控制台查看原始图片
  • 使用 Canvas 绘制水印,性能优良
  • 水印图案会被缓存,不会重复绘制
  • 容器大小变化时会自动重新计算水印位置