vue实现添加水印(给页面添加背景水印、给图片添加水印)

前言

水印挺常见的,一般就是用来标识来源。下面介绍一下如何实现背景水印和图片水印,水印的核心是canvas,最好对canvas有些了解。

背景水印

参考文章:VUE项目前端页面添加水印 这篇文章写的很详细了,我这里主要是参考该文章自己实现一下。

<template>
    <div class="main">

    </div>
</template>

<script setup lang="ts">
import {
    
     onMounted } from 'vue';
// 生成水印
const initWatermark = () => {
    
    
    // 创建一个canvas
    const canvas = document.createElement('canvas');
    // 设置画布的宽高
    canvas.width = 200;
    canvas.height = 200;
    // 获取画笔
    const ctx = canvas.getContext('2d');
    // 水印,水印实际上就是将文字添加到画布上
    ctx.font = '30px Arial'; // 设置字体大小和字体
    ctx.rotate(-0.4);// 设置文字旋转角度

    // 创建实体水印
    // ctx.fillStyle = 'rgba(0,0,0,.3)'; // 颜色
    // ctx.fillText('这是水印', canvas.width / 6, canvas.height / 2);// 设置显示文字和偏移量

    // 创建虚心水印
    // ctx.strokeStyle = 'rgba(0,0,0,.3)';
    // ctx?.strokeText('这是水印', canvas.width / 6, canvas.height / 2);

    // 渐变水印
    const gradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
    gradient.addColorStop(0, 'red');
    gradient.addColorStop(0.5, 'yellow');
    gradient.addColorStop(1, 'green');
    ctx.fillStyle = gradient; // 颜色
    ctx.fillText('这是水印', canvas.width / 6, canvas.height / 2);// 设置显示文字和偏移量

    // 将画布转成图片
    const img = canvas.toDataURL();
    const main = document.querySelector('.main');
    main.style.backgroundImage = `url(${
    
    img})`;
};

onMounted(() => {
    
    
    initWatermark();
});
</script>

<style lang="scss" scoped>
.main{
    
    
    width: 600px;
    height: 400px;
    border: 1px solid red;
    margin: 0 auto;
}
</style>

实体水印
在这里插入图片描述

虚心水印
在这里插入图片描述

渐变水印
在这里插入图片描述

防止水印被取消

文章中提出了一个有意思的如何防止水印被清除掉。对于开发人员很清楚,水印实际上就是一个背景图,在控制台了把背景取消就可以被清除掉。

一种方法是不允许打开控制台,这个需要监听键盘、监听鼠标右键。取消掉其默认行为就好。

main?.addEventListener('contextmenu', (event) => {
    
    
     event.preventDefault();
 });

另一种方法就是文章中提供的MutationObserver,通过监听dom树的变化来实现

// 监听水印的变化
const handleWatermark = () => {
    
    
    // 获取需要观察的节点
    const target = document.querySelector('.main');
    // 观察器配置
    const config = {
    
    
        attributes: true, // 监听目标元素属性的变化
        childList: true, // 监听目标原型子节点的变化
        subtree: false // 是否观察后代的变化。默认false
    };
    // 创建观察器
    const observer = new MutationObserver((abc) => {
    
    
        // console.log(abc);
        // 获取背景图片
        const bgi = target?.style?.backgroundImage;
        console.log('背景的值:', bgi);
        if (!bgi) {
    
    
            // 当背景被取消后,重新添加
            initWatermark();
        }
    });
    // 开始观察
    observer.observe(target, config);
    // 停止观察
    // observer.disconnect()
};

在这里插入图片描述

给图片添加水印

就以csdn为例,当上传图片后,图片会自动添加上水印。
基本原理是:

  • 拿到上传的图片
  • 将图片绘制到画布上
  • 在画布上添加水印
  • 将画布转为图片
  • 将新的图片数据传给后台

下面是一个简单的例子

<template>
    <div class="main">
        <input type="file" id="fileInput" accept="image/*" :multiple="false" />
       <img v-if="imgUrl" :src="imgUrl" class="img" />
    </div>
</template>

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

const imgUrl = ref('');

onMounted(() => {
    
    
    const fileInput = document.getElementById('fileInput');
    // 监听文件上传
    fileInput?.addEventListener('change', handleFileChange);
});

// 处理文件
const handleFileChange = async(event) => {
    
    
    const [file] = event.target.files;
    // 读取文件
    const dataUrl = await readFile(file);
    // 创建图片
    const img = await createImage(dataUrl);
    // 生成水印
    imgUrl.value = createWatermark(img);
};

// 文件读取
const readFile = file => {
    
    
    return new Promise((resolve) => {
    
    
        const reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = () => {
    
    
            resolve(reader.result);
        };
    });
};

// 生成图片
const createImage = dataUrl => {
    
    
    return new Promise((resolve) => {
    
    
        const img = new Image();
        img.src = dataUrl;
        img.onload = () => {
    
    
            resolve(img);
        };
    });
};

// 生成水印
const createWatermark = img => {
    
    
    // 创建canvas
    const canvas = document.createElement('canvas');
    canvas.width = img.width;
    canvas.height = img.height;
    // 绘制图片
    const ctx = canvas.getContext('2d');
    ctx.drawImage(img, 0, 0);
    // 添加水印
    ctx.font = '20px Arial';
    ctx.rotate(-0.4);
    ctx.fillStyle = 'green';
    ctx.fillText('这是水印', canvas.width * 0.1, canvas.height * 0.3);
    // 返回带有水印的图片
    return canvas.toDataURL();
};
</script>

<style lang="scss" scoped>
.main{
    
    
    width: 600px;
    height: 400px;
    border: 1px solid red;
    margin: 0 auto;
}

.img{
    
    
    width:300px;
    height: 200px;
    margin-top: 50px;
}
</style>

效果
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_41897680/article/details/130780482