页面效果

实现步骤
- 获取Canvas元素,并设置其宽高为屏幕宽高,同时将像素比乘以窗口设备像素比,以保证显示效果正确。
- 设置水印的样式,包括颜色、字体大小、倾斜角度、行高、左右边距、上下边距和垂直间距等参数。
- 编写绘制水印的函数
drawWatermark(),设置水印文本,并进行旋转、分行等处理,最后使用循环生成每个水印的位置坐标,并在对应位置绘制水印文本。
代码展示
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Canvas 水印</title>
<style>
* {
padding: 0;
margin: 0;
}
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
canvas {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 200%;
height: 200%;
z-index: -1;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<div>
<h1>Canvas 水印示例</h1>
<p>这是一个基于 Canvas 实现的水印效果,可以在多行文本之间设置间距,并倾斜显示。</p>
</div>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
canvas.width = window.innerWidth * window.devicePixelRatio;
canvas.height = window.innerHeight * window.devicePixelRatio;
var color = 'rgba(0, 0, 0, 0.2)';
var fontSize = 12 * window.devicePixelRatio;
var angle = -45 * Math.PI / 180;
var lineHeight = 30 * window.devicePixelRatio;
var marginLeft = 10 * window.devicePixelRatio;
var marginTop = 30 * window.devicePixelRatio;
var verticalOffset = 50 * window.devicePixelRatio;
function drawWatermark() {
var text = '这是水印示例\n多行展示内容';
ctx.fillStyle = color;
ctx.font = fontSize + 'px Arial';
ctx.rotate(angle);
var lines = text.split('\n');
var numLines = Math.ceil(canvas.height / lineHeight);
var lineWidth = Math.max(...lines.map(line => ctx.measureText(line).width));
var numCols = Math.ceil(canvas.width / (lineWidth + marginLeft));
var offset = Math.ceil( canvas.width / 2);
for (var i = 0; i < numLines; i++) {
for (var j = 0; j < numCols; j++) {
lines.forEach(function (line, index) {
var x = (j * (lineWidth + marginLeft)) + marginLeft - offset;
var y = (i * lines.length + index + 1) * lineHeight + marginTop + (i * verticalOffset);
ctx.fillText(line, x, y);
});
}
}
}
drawWatermark();
window.addEventListener('resize', function () {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawWatermark();
});
</script>
</body>
</html>
代码解释
var y = (i * lines.length + index + 1)
*
lineHeight + marginTop
+
(i * verticalOffset);
i * lines.length: 这部分是为了确保每行水印在垂直方向上有一定的间距,通过将每行的高度乘以总行数,来确定当前行的基础位置。
index + 1: 这部分是为了让每行多行水印中的每行都有一定的垂直偏移,确保多行水印之间不会重叠。
lineHeight: 表示每行水印的高度,即每行文字的行高。
marginTop: 是水印距离画布顶部的距离,用于调整水印的垂直起始位置。
i * verticalOffset: 这部分是为了让每列水印在垂直方向上也有一定的间距,通过将每列的垂直偏移乘以列数,来确定当前列的基础位置。
vue 方式
<template>
<div>
<canvas id="canvas"></canvas>
</div>
</template>
<script>
export default {
mounted() {
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth * window.devicePixelRatio;
canvas.height = window.innerHeight * window.devicePixelRatio;
function drawWatermark() {
}
drawWatermark();
window.addEventListener('resize', function () {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawWatermark();
});
},
beforeDestroy() {
window.removeEventListener('resize', this.drawWatermark);
}
};
</script>
react 方式
import React, { useEffect } from 'react';
const Watermark = () => {
useEffect(() => {
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth * window.devicePixelRatio;
canvas.height = window.innerHeight * window.devicePixelRatio;
const drawWatermark = () => {
};
drawWatermark();
const handleResize = () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawWatermark();
};
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);
return <canvas id="canvas"></canvas>;
};
export default Watermark;
