canvas水印生成

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()

通过以上改进,实现水印的统一格式,自动对齐以及参数配置,避免了重复工作并提升了代码的可维护性。

相关推荐
灵感__idea6 小时前
Hello 算法:贪心的世界
前端·javascript·算法
killerbasd9 小时前
牧苏苏传 我不装了 4/7
前端·javascript·vue.js
橘子编程10 小时前
JavaScript与TypeScript终极指南
javascript·ubuntu·typescript
叫我一声阿雷吧10 小时前
JS 入门通关手册(45):浏览器渲染原理与重绘重排(性能优化核心,面试必考
javascript·前端面试·前端性能优化·浏览器渲染·浏览器渲染原理,重排重绘·reflow·repaint
大家的林语冰10 小时前
《前端周刊》尤大开源 Vite+ 全家桶,前端工业革命启动;尤大爆料 Void 云服务新产品,Vite 进军全栈开发;ECMA 源码映射规范......
前端·javascript·vue.js
jiayong2311 小时前
第 8 课:开始引入组合式函数
前端·javascript·学习
天若有情67311 小时前
【C++原创开源】formort.h:一行头文件,实现比JS模板字符串更爽的链式拼接+响应式变量
开发语言·javascript·c++·git·github·开源项目·模版字符串
yuki_uix12 小时前
重排、重绘与合成——浏览器渲染性能的底层逻辑
前端·javascript·面试
止观止12 小时前
拥抱 ESNext:从 TC39 提案到生产环境中的现代 JS
开发语言·javascript·ecmascript·esnext
时寒的笔记13 小时前
js逆向7_案例惠nong网
android·开发语言·javascript