canvas水印生成
在大多数内部项目中,水印是一个常见需求。过去,当新项目需要添加水印时,通常是从旧项目中复制水印代码。这种做法不仅带来了大量重复工作,还导致了可维护性差的问题。另外,当前的方法在手动调整水印位置时,常常无法根据内容自动对齐。
本文旨在根据产品侧的规范设计方法,解决现有方法中的问题:
- 统一格式,遵循需求文档
- 自动居中对齐
- 参数可配置,例如间距、旋转角度、透明度
以下是改进后的水印代码:
typescript
import dayjs from 'dayjs'
class WatermarkManager {
private watermarkId = 'custom-watermark-canvas'
// 创建水印
private createWatermark(username: string, angle: number, xGap: number, yGap: number): void {
// 创建 canvas 元素
const canvas = document.createElement('canvas')
canvas.id = this.watermarkId
canvas.width = window.innerWidth
canvas.height = window.innerHeight
canvas.style.position = 'fixed'
canvas.style.top = '0'
canvas.style.left = '0'
canvas.style.zIndex = '1000'
canvas.style.pointerEvents = 'none'
canvas.style.opacity = '0.5'
const ctx = canvas.getContext('2d')
if (ctx) {
ctx.clearRect(0, 0, canvas.width, canvas.height)
ctx.font = '18px Arial'
const firstContent = `xxxxx平台 ${username} ${dayjs().format('YYYY/MM/DD')}`
const secondContent = '未经允许,不得外泄'
const textWidth = ctx.measureText(firstContent).width
const textHeight = 18
ctx.font = '16px Arial'
const subTextWidth = ctx.measureText(secondContent).width
const subTextHeight = 16
const totalHeight = textHeight + subTextHeight + 10 // 两行文字的总高度
const maxWidth = Math.max(textWidth, subTextWidth) // 两行文字的最大宽度
for (let x = 0; x < canvas.width; x += xGap) {
for (let y = 0; y < canvas.height; y += yGap) {
ctx.save()
ctx.translate(x + maxWidth / 2, y + totalHeight / 2)
ctx.rotate(angle * Math.PI / 180)
// 绘制第一行文字
ctx.font = '18px Arial'
ctx.fillStyle = 'rgba(0, 0, 0, 0.15)'
ctx.fillText(firstContent, -textWidth / 2, 0)
// 绘制第二行文字
ctx.font = '16px Arial'
ctx.fillStyle = 'rgba(0, 0, 0, 0.15)'
ctx.fillText(secondContent, -subTextWidth / 2, textHeight + 10)
ctx.restore()
}
}
}
// 添加 canvas 到页面
document.body.appendChild(canvas)
}
// 移除水印
private removeWatermark(): void {
const canvas = document.getElementById(this.watermarkId)
if (canvas)
canvas.remove()
}
// 设置水印
public setWatermark(username: string, angle: number = -30, xGap: number = 200, yGap: number = 100): void {
this.removeWatermark()
this.createWatermark(username, angle, xGap, yGap)
}
// 清理水印
public clearWatermark(): void {
this.removeWatermark()
}
}
const watermarkManager = new WatermarkManager()
export default watermarkManager
使用示例
js
const watermarkManager = new WatermarkManager()
// 设置水印
watermarkManager.setWatermark('用户名', -30, 280, 280)
// 清空水印
watermarkManager.clearWatermark()
通过以上改进,实现水印的统一格式,自动对齐以及参数配置,避免了重复工作并提升了代码的可维护性。