Vue3 + TypeScript 实现添加水印功能

1,733 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第11天,点击查看活动详情

概述

在项目开发的过程中时常会遇到文档添加的水印的功能,今天我们使用 Vue3 来实现一个添加水印的功能,这里我把自己封装的过程和代码和大家分享一下,希望能够得到大家的批评和建议。

项目初始化

首先我们新建一个项目,执行如下命令

pnpm create vite vue-watermark

选择 vue ,接着选择 vue-ts ,回车,等待项目安装完成, cd 进入项目根目录下,接着安装项目需要的依赖包

pnpm install

安装完成后,我们启动项目

pnpm run dev

控制台输出如下内容

  vite v2.9.10 dev server running at:

  > Local: http://localhost:3000/
  > Network: use `--host` to expose

  ready in 353ms.

说明项目正常启动了,下面我们开始添加水印

添加水印

首先我们来说下添加水印的原理,这里我们使用 canvas 来生成一张画布,然后在画布上添加我们需要的水印, 接着使用 canvastoDataURL 方法生成一张图片,将生成的图片设置为挂载元素的背景图,水印功能就添加完成了。

我们先删除项目中多余的内容,然后新建组件文件 src/components/watermark.vue, 添加如下内容

<template>
    <div ref="waterMarkRef" :style="{ height, width }"></div>
</template>

<script setup lang="ts">
import { Ref, ref, onMounted, unref, toRefs } from 'vue'

const props = defineProps({
    width: {
        type: String,
        default: "600px",
    },
    height: {
        type: String,
        default: "300px",
    },
})
const { width, height } = toRefs(props)
const waterMarkRef = ref<HTMLDivElement | null>(null);

</script>

考虑到添加水印的方法有可能需要在多个地方调用,所以我们可以将生成水印元素需要的属性在每次调用函数的时候传递进去。

interface WaterMarkInter {
    elRef: Ref<HTMLDivElement>;
    waterMark: string; 
    color?:string; 
    angle?: number; 
    width?: number; 
    height?: number; 
    alpha?: number;
    size?: string
}
function waterMarker({elRef, waterMark="水印", color = "#e9e9e9", angle=-15, size="24",alpha=0.5, width=600, height=300}: WaterMarkInter) {
    if (!elRef) {
        return
    }
    
    const element = unref(elRef) as HTMLDivElement
    let canvasEle = document.createElement('canvas');
    element.appendChild(canvasEle);
    canvasEle.width = width;
    canvasEle.height = height;
    canvasEle.style.display = 'none';
    canvasEle.style.zIndex = '9'
    let cans = canvasEle.getContext('2d') as CanvasRenderingContext2D;
    cans.rotate(angle * Math.PI / 180);
    cans.font = "500 30px Microsoft JhengHei";
    cans.fillStyle = color;
    cans.textAlign = 'center';
    cans.textBaseline = 'middle';
    cans.globalAlpha = alpha
    cans.font = '1000 ' + size + 'px ' + ' Microsoft JhengHei'
    for (let i = (document.body.offsetHeight * 0.5) * -1; i < 800; i += 160) {
        for (let j = 0; j < document.body.offsetHeight * 1.5; j += 60) {
            cans.fillText(waterMark, i, j)
        }
    }
    element.style.backgroundImage = "url(" + canvasEle.toDataURL("image/png") + ")";
}

onMounted(() => {
    waterMarker({
        elRef: waterMarkRef as Ref<HTMLDivElement>, 
        waterMark: "测试",
        color:"skyblue",
        size: "28"
    })
})

测试一下,可以看到如下效果

截屏2022-06-10 下午11.11.33.png

说明我们的水印添加完成了。

当然,我们也可以使用 watermark-dom 这个添加水印的插件库,使用起来也非常方便,先安装

pnpm install watermark-dom
pnpm install @types/watermark-dom

然后调用

watermark.init({
  watermark_id: 'wm_div_id',          //水印的id
  watermark_prefix: 'mask_div_id',    //小水印的id前缀
  watermark_txt:"测试水印",             //水印的内容
  watermark_x:20,                     //水印起始位置x轴坐标
  watermark_y:20,                     //水印起始位置Y轴坐标
  watermark_rows:0,                   //水印行数
  watermark_cols:0,                   //水印列数
  watermark_x_space:100,              //水印x轴间隔
  watermark_y_space:50,               //水印y轴间隔
  watermark_font:'微软雅黑',           //水印字体
  watermark_color:'black',            //水印字体颜色
  watermark_fontsize:'18px',          //水印字体大小
  watermark_alpha:0.15,               //水印透明度,要求设置在大于等于0.005
  watermark_width:100,                //水印宽度
  watermark_height:100,               //水印长度
  watermark_angle:15,                 //水印倾斜度数
  watermark_parent_width:0,      //水印的总体宽度(默认值:body的scrollWidth和clientWidth的较大值)
  watermark_parent_height:0,     //水印的总体高度(默认值:body的scrollHeight和clientHeight的较大值)
  watermark_parent_node:null     //水印插件挂载的父元素element,不输入则默认挂在body上
})