uniapp+vue3开发微信小程序,实现页面动态水印的方法

客户从事房产中介行业,对房源及客户的信息保密性要求较高,希望能实现以登录用户手机号后四位的动态重复水印。

网页中水印可以通过 css 背景图方式实现,而微信小程序环境却无法顺利运行。最终我选择使用 canvas 的方式实现。

示例代码

util.js

/*
	页面水印,页面中要有id="watermarkCanvas",type="2d"的canvas
	<canvas class="watermark" canvas-id="watermarkCanvas" id="watermarkCanvas" type="2d"></canvas>
*/
export const watermark = (context, canvasId = "watermarkCanvas") => {
	const user = uni.getStorageSync('user');
	//console.log(user);
	//console.log('watermark');
	if (!user || !user.phone) return;
	
	// 获取手机号后四位
	const text = user.phone.slice(-4);
	const query = uni.createSelectorQuery().in(context);
	query.select(`#${canvasId}`)
	    .fields({ node: true, size: true })
	    .exec((res) => {
	
	        if (res[0] && res[0].node) {
                const canvas = res[0].node;
                const ctx = canvas.getContext('2d');
                const dpr = uni.getSystemInfoSync().pixelRatio;
                canvas.width = res[0].width * dpr;
                canvas.height = res[0].height * dpr;
                ctx.scale(dpr, dpr);

                const textWidth = 100;
                const textHeight = 50;
                const gap = 50;

                ctx.font = '14px Arial';
                ctx.fillStyle = 'rgba(85, 170, 255, 0.5)';
                ctx.textAlign = 'center';
                ctx.textBaseline = 'middle';

                for (let x = 0; x < canvas.width; x += textWidth + gap) {
                    for (let y = 0; y < canvas.height; y += textHeight + gap) {
                        ctx.save();
                        ctx.translate(x + textWidth / 2, y + textHeight / 2);
                        ctx.rotate(-30 * Math.PI / 180);
                        ctx.fillText(text, 0, 0);
                        ctx.restore();
                    }
                }
	        } else {
	            console.error('Failed to get canvas node.');
	        }
	    });
}

room.vue

<template>
	<view class="watermark-container">
		<!-- 隐藏的 Canvas 元素 -->
		<canvas class="watermark" canvas-id="watermarkCanvas" id="watermarkCanvas" type="2d"></canvas>
		<view class="container">
			<!--页面主体内容-->
		</view>
	</view>
</template>

<script>
	import { watermark } from '@/utils/util'
	onReady() {
		watermark(this)
	},
</script>

<style>
	.watermark-container {
	  position: relative;
	  width: 100%;
	  min-height: 100vh;
	  height: 100%; /*确保容器有高度 */
	  background-size: auto; /* 确保背景图片按原尺寸显示 */
	}
	.watermark {
	    position: absolute;
	    top: 0;
	    left: 0;
	    width: 100%;
	    height: 100%;
	    pointer-events: none;
	    opacity: 0.5;
	    z-index: -1;
	}
</style>

注意事项

  • 页面中要有 id=”watermarkCanvas”,type=”2d” 的 canvas 元素,注意必须设置 type=”2d”。
  • .watermark-container 要设置 min-height: 100vh;,否则水印可能只加载到页面内容结束位置。
  • 水印方法要在 onReady 中调用,因为 onLoad 或者 onShow 中,页面结构可能还没加载完。
  • 如果页面数据列表动态加载导致页面变长,那么需要定期监听页面高度变化重新调用 watermark 方法。