Watermark.vue 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. <template>
  2. <div ref="watermarkContainer" class="watermark-container">
  3. <canvas ref="watermarkCanvas" class="watermark-canvas"></canvas>
  4. </div>
  5. </template>
  6. <script>
  7. export default {
  8. name: 'Watermark',
  9. props: {
  10. text: {
  11. type: String,
  12. default: '',
  13. },
  14. fontSize: {
  15. type: Number,
  16. default: 16,
  17. },
  18. color: {
  19. type: String,
  20. default: 'rgba(219, 219, 219)',
  21. },
  22. angle: {
  23. type: Number,
  24. default: -25,
  25. },
  26. },
  27. data() {
  28. return {
  29. isInit: false,
  30. }
  31. },
  32. watch: {
  33. text: {
  34. handler() {
  35. this.drawWatermark()
  36. },
  37. immediate: true,
  38. },
  39. },
  40. mounted() {
  41. this.initWatermark()
  42. window.addEventListener('resize', this.handleResize)
  43. },
  44. beforeDestroy() {
  45. window.removeEventListener('resize', this.handleResize)
  46. },
  47. methods: {
  48. initWatermark() {
  49. this.isInit = true
  50. this.drawWatermark()
  51. },
  52. drawWatermark() {
  53. if (!this.isInit || !this.text) return
  54. const canvas = this.$refs.watermarkCanvas
  55. const ctx = canvas.getContext('2d')
  56. const container = this.$refs.watermarkContainer
  57. // 设置canvas大小与容器一致
  58. canvas.width = container.offsetWidth || window.innerWidth
  59. canvas.height = container.offsetHeight || window.innerHeight
  60. // 清空画布
  61. ctx.clearRect(0, 0, canvas.width, canvas.height)
  62. // 设置水印样式
  63. ctx.font = `${this.fontSize}px Arial`
  64. ctx.fillStyle = this.color
  65. ctx.textAlign = 'center'
  66. ctx.textBaseline = 'middle'
  67. ctx.globalAlpha = 0.8 // 增加全局透明度
  68. // 计算水印间距和布局 - 调整为5*5分布
  69. const textWidth = ctx.measureText(this.text).width
  70. // 计算5*5分布需要的间距,进一步减小垂直间距
  71. const gapX = canvas.width / 5
  72. const gapY = canvas.height / 5
  73. // 调整起始位置,确保边缘水印完整显示
  74. const startX = textWidth * 2
  75. const startY = textWidth * 1.2
  76. // 绘制重复的水印,实现5*5分布
  77. for (let x = startX; x < canvas.width; x += gapX) {
  78. for (let y = startY; y < canvas.height; y += gapY) {
  79. ctx.save()
  80. ctx.translate(x, y)
  81. ctx.rotate((Math.PI / 180) * this.angle)
  82. ctx.fillText(this.text, 0, 0)
  83. ctx.restore()
  84. }
  85. }
  86. },
  87. handleResize() {
  88. this.$nextTick(() => {
  89. this.drawWatermark()
  90. })
  91. },
  92. },
  93. }
  94. </script>
  95. <style scoped>
  96. .watermark-container {
  97. position: fixed;
  98. top: 0;
  99. left: 0;
  100. width: 100%;
  101. height: 100%;
  102. pointer-events: none;
  103. z-index: 9998;
  104. }
  105. .watermark-canvas {
  106. width: 100%;
  107. height: 100%;
  108. }
  109. </style>