index.vue 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. <template>
  2. <div :class="classes" :style="styles">
  3. <slot />
  4. <canvas
  5. ref="canvas"
  6. :width="width"
  7. :height="height"
  8. style="display:none"
  9. />
  10. <div v-if="mask" class="ibps-watermark__mask" :style="maskStyle" />
  11. </div>
  12. </template>
  13. <script>
  14. /**
  15. * 水印组件
  16. */
  17. export default {
  18. name: 'ibps-watermark',
  19. /**
  20. * 属性参数
  21. * @member props
  22. * @property {String|Array} text 水印文字, 多行文本可以传数组
  23. * @property {Number} [lineHeight=10] 行距,多行文本有效
  24. * @property {Number} [width=200] 画布的宽度
  25. * @property {Number} [height=200] 画布的高度
  26. * @property {String} [font] 水印文字的字体
  27. * @property {Number} [rotate] 文字旋转角度,默认:-20
  28. * @property {String} [color] 水印文字字体颜色 默认:rgba(100, 100, 100, 0.1)
  29. * @property {Number} [x] 文字在画布的坐标x
  30. * @property {Number} [y] 文字在画布的坐标y
  31. * @property {Boolean} [mask] mask 遮罩模式
  32. */
  33. props: {
  34. disabled: Boolean,
  35. text: {
  36. type: [String, Array],
  37. default: ''
  38. },
  39. lineHeight: {
  40. type: Number,
  41. default: 10
  42. },
  43. width: {
  44. type: Number,
  45. default: 300
  46. },
  47. height: {
  48. type: Number,
  49. default: 300
  50. },
  51. font: {
  52. type: String,
  53. default: '20px 黑体'
  54. },
  55. rotate: {
  56. type: Number,
  57. default: -20
  58. },
  59. color: {
  60. type: String,
  61. default: 'rgba(100, 100, 100, 0.1)'
  62. },
  63. x: {
  64. type: Number,
  65. default: 0
  66. },
  67. y: {
  68. type: Number,
  69. default: 100
  70. },
  71. mask: {
  72. type: Boolean,
  73. default: true
  74. }
  75. },
  76. data() {
  77. return {
  78. dataUrl: null
  79. }
  80. },
  81. computed: {
  82. classes() {
  83. return {
  84. 'ibps-watermark': true,
  85. 'is-mask': this.mask,
  86. 'is-disabled': this.disabled
  87. }
  88. },
  89. styles() {
  90. if (!this.dataUrl || this.mask || this.disabled) return null
  91. return {
  92. backgroundImage: `url(${this.dataUrl})`
  93. }
  94. },
  95. maskStyle() {
  96. if (!this.dataUrl || !this.mask || this.disabled) return null
  97. return {
  98. backgroundImage: `url(${this.dataUrl})`
  99. }
  100. }
  101. },
  102. watch: {
  103. text() {
  104. this.reset()
  105. this.draw()
  106. }
  107. },
  108. mounted() {
  109. !this.disabled && this.draw()
  110. },
  111. methods: {
  112. draw() {
  113. if (!this.text) return
  114. const textArray = [].concat(this.text)
  115. const canvas = this.$refs.canvas
  116. const ctx = canvas.getContext('2d')
  117. const rotate = this.rotate * Math.PI / 180
  118. ctx.clearRect(0, 0, this.width, this.height)
  119. ctx.rotate(rotate)
  120. ctx.font = this.font
  121. ctx.fillStyle = this.color
  122. const fontSize = parseInt(ctx.font) || 20
  123. textArray.forEach((text, index) => {
  124. const y = this.y + (fontSize + this.lineHeight) * index
  125. ctx.fillText(text, this.x, y)
  126. })
  127. this.dataUrl = ctx.canvas.toDataURL()
  128. },
  129. reset() {
  130. const canvas = this.$refs.canvas
  131. const ctx = canvas.getContext('2d')
  132. ctx.clearRect(0, 0, this.width, this.height)
  133. const rotate = this.rotate * Math.PI / 180
  134. ctx.rotate(-rotate)
  135. }
  136. }
  137. }
  138. </script>