vue2 使用canvas生成水印

参考 src/views/other/waterMarker/index.vue · yuanzbz/vue-admin-perfect - Gitee.com

记录使用canvas生成水印的过程以及水印样式的配置。

  • 效果图

局部水印效果图

全局水印效果图 

 

  • 实现原理

生成一个canvas画布,指定水印的内容,倾斜度,颜色等样式,转成图片格式作为背景图布满容器。

  • 创建waterMarker.js文件
/*
* 生成一个canvas画布,转化成图片格式,重复排列布满容器
*/
function watermark (options) {
  const {
    container = document.body, // 容器
    width = '240', // canvas元素宽,调整水印的水平间距
    height = '200', // canvas元素高, 调整水印的垂直间距
    textAlign = 'left', // 文字对齐
    textBaseline = 'bottom', // 基准线
    font = '16px Microsoft Yahei', // 字体大小及样式
    fillStyle = '#000', // 自定义水印的颜色
    content = '小香菜今天吃什么', // 水印内容
    globalAlpha = 0.3, // 设置图形和图像透明度的值
    rotate = 16, // 文字旋转角度
    zIndex = 1000, // 元素堆叠顺序
    isCancel =true
  } = options

  const canvas = document.createElement('canvas')
  canvas.setAttribute('width', width)
  canvas.setAttribute('height', height)
  const ctx = canvas.getContext('2d') // 获取 canvas2d 上下文
  ctx.globalAlpha = globalAlpha
  ctx.textAlign = textAlign
  ctx.textBaseline = textBaseline
  ctx.font = font
  ctx.fillStyle = fillStyle
  ctx.rotate((Math.PI * rotate) / 180)
  ctx.fillText(content, -10, 150)  // 调整水印倾斜角度时,需调整该项

  const base64Url = canvas.toDataURL() // 返回一个包含图片展示的 data URI

  const __wm = document.querySelector('.__yoyo__wm')// 选择器
  const watermarkDiv = __wm || document.createElement('div')
  const styleStr = `
    position:absolute;
    top:0px;
    left:0px;
    width:100%;
    height:100%;
    z-index:${zIndex};
    pointer-events:none;
    background-repeat:repeat;
    background-image:url('${base64Url}')`

  watermarkDiv.setAttribute('style', styleStr)
  watermarkDiv.classList.add('__yoyo__wm') // 为元素添加“__yoyo__wm”类名

  container.style.position = 'relative'
  container.appendChild(watermarkDiv) // 添加元素

}
export default watermark
  • 使用watermark方法生成水印
<template>
  <div class="waterMarker-container common-container yoyo-water-marker">
    <div class="waterMarker-content-container">
      <div class="waterMarker-button-container">
        <div class="waterMarker-button partWaterMark" @click="setWaterMarker(1)">生成局部水印</div>
        <div class="waterMarker-button globalWaterMark" @click="setWaterMarker(2)">生成全局水印</div>
        <div class="waterMarker-button defaultColorWaterMark" @click="setWaterMarker(3)">生成默认颜色水印</div>
        <div class="waterMarker-button targetWaterMark">
          <el-input class="opacity-input" v-model="targetColor" placeholder="#e5f3fd"></el-input>
          <div class="targetColor-button" @click="setWaterMarker(4)">生成指定颜色水印</div>
        </div>
        <div class="waterMarker-button randColorWaterMark" @click="setWaterMarker(5)">生成随机颜色水印</div>
        <div class="waterMarker-button opacityWaterMark">
          <el-input class="opacity-input" v-model="opacityValue"></el-input>
          <div class="opacity-button" @click="setWaterMarker(6)">设置透明度</div>
        </div>
        <div class="waterMarker-button clearWaterMark" @click="setWaterMarker(7)">不显示水印</div>
      </div>
      <div class="waterMarker-config">
        <el-descriptions title="配置项 " :column="1" border class="descriptions">
          <el-descriptions-item label="content"> 水印内容,默认为 '小香菜今天吃什么' </el-descriptions-item>
          <el-descriptions-item label="container"> 水印容器,默认生成在 document.body 下面 </el-descriptions-item>
          <el-descriptions-item label="globalAlpha"> 设置图形和图像透明度的值,默认为 0.3 </el-descriptions-item>
          <el-descriptions-item label="height"> 水印高度,默认为 240,该值可调整水印的垂直间距 </el-descriptions-item>
          <el-descriptions-item label="width"> 水印宽度,默认为 100,该值可调整水印的水平间距 </el-descriptions-item>
          <el-descriptions-item label="fillStyle"> 水印颜色,默认为 '#000' </el-descriptions-item>
          <el-descriptions-item label="textAlign"> 文字对齐,默认为 'left' </el-descriptions-item>
          <el-descriptions-item label="textBaseline"> 基准线,默认为 'bottom' </el-descriptions-item>
          <el-descriptions-item label="rotate"> 文字旋转角度,默认为 '16' 计算方式为 (Math.PI * rotate) / 180 </el-descriptions-item>
          <el-descriptions-item label="iconStyle"> 图标的样式,默认样式为 { width: "1em", height: " 1em" } </el-descriptions-item>
        </el-descriptions>
      </div>
    </div>
  </div>
</template>

<script>
import watermark from '@/utils/waterMarker.js'
import { getColor } from '@/utils/index.js'
export default {
  name: 'index',
  data(){
    return{
      opacityValue: 0.2,
      selectType: 1,
      options: {
        rotate: -30,
        globalAlpha: 0.2,
      },
      targetColor: '',
      colorList: [],
    }
  },
  mounted () {
    this.getRandColor()
    this.$nextTick(() =>{
      this.setWaterMarker(1)
    })
  },
  methods:{
    // 随机生成三十种颜色
    getRandColor(){
      for (let i = 0; i < 30; i++) {
        this.colorList.push(getColor())
      }
    },
    // 生成随机数
    getRandom(start, end) {
      const differ = end - start
      const random = Math.random()
      return (start + differ * random).toFixed(0)
    },
    // 设置水印
    setWaterMarker(type){
      switch (type) {
        case 1:
          this.selectType = type
          this.options.container = document.getElementsByClassName('yoyo-water-marker')[0]
          watermark(this.options)
          return;
        case 2:
          this.selectType = type
          delete this.options.container
          watermark(this.options)
          return;
        case 3:
          this.options.fillStyle = '#000'
          watermark(this.options)
          return;
        case 4:
          this.options.fillStyle = this.targetColor
          watermark(this.options)
          return;
        case 5:
          this.options.fillStyle = this.colorList[this.getRandom(0, 30)]
          watermark(this.options)
          return;
        case 6:
          this.options.globalAlpha = this.opacityValue
          watermark(this.options)
          return;
        case 7:
          this.$nextTick(() => {
            const wm = document.getElementsByClassName('__yoyo__wm')[0]
            if (wm) {
              if(this.selectType===-1){
                wm.remove()
              }else {
                document.body.removeChild(wm)
              }
            }
          })
      }
    },
  }
}
</script>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值