Skip to content
On this page

watermark

水印

介绍

和别的地方的水印使用 canvas 不同,这里使用 css 实现,所以水印的样式可以使用css自定义。同时可以使用自定义插槽name=content自定义样式


原理是获取 svg的内容,本身的 svg 不需要显示, 然后通过 createObjectURL 把内容转换成 blob,然后通过 css 设置 background-image 属性,实现水印。

效果

abcd
ABCD

原理

  1. 获取 svg 父元素的 innerHTML ,也就是获取 svg 的内容
  2. 使用 new Blobtype: 'image/svg+xml',形成一个 blob 实例
  3. 通过 URL.createObjectURL 方法传入 blob 实例生成一个 url,
  4. 最后把 url 设置为背景图片

核心源码

vue
<template>
  <div class="relative h-[200px]">
    <slot/>
      <div 
      class="absolute w-full h-full inset-0 text-gray-200"
      :style="{
        backgroundImage: `url(${watermarkUrl})`,
        zIndex: 10,
        height: '200px'
      }">
      <!-- 不需要显示 -->
        <div ref="svgRef" v-show="false">
          <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
            :viewBox="`0 0 ${100} ${100}`" :width="`${100}`" :height="`${100}`" :style="{
              padding: `0 ${0}px ${0}px 0`,
              opacity: 0.5,
            }">
            <foreignObject
            x="0" 
            y="0" 
            :width="100" 
            :height="100">
              <div xmlns="http://www.w3.org/1999/xhtml" :style="{
                transform: `translate(${0}px, ${0}px) rotate(${-22}deg)`,
                transformOrigin: 'center',
              }">
                <!-- 默认值 -->
               <slot name="content">
                  <span :style="{  fontSize: `${14}px`, color: 'red' }">
                    {{content}}
                  </span>
                </slot>
              </div>
            </foreignObject>
          </svg>
        </div>
      </div>
  </div>
</template>
<script lang="ts" setup>
import { onMounted, ref, computed, reactive, watch, Ref } from "vue";
const watermarkUrl = ref("");

defineProps({
  content:{
    type:String,
    default:"abbr"
  }
})
const svgRef: Ref<SVGElement | null> = ref(null)
function revokeWatermarkUrl() {
  if (watermarkUrl.value) {
    URL.revokeObjectURL(watermarkUrl.value)
  }
}

function svgToBlobUrl(svgStr: string) {
  const svgBlob = new Blob([svgStr], {
    type: 'image/svg+xml',
  })
  return URL.createObjectURL(svgBlob)
}

const resize = async function () {
  // DOM 更新之后才可以获取样式
  await nextTick()
  revokeWatermarkUrl()
  watermarkUrl.value = svgToBlobUrl(svgRef.value!.innerHTML)
}

resize()
</script>