当前位置: 首页 > 工具软件 > watermark.js > 使用案例 >

自适配传数据 加水印 数据 Watermark.js

景鸿才
2023-12-01
/**
 * 引用: import * as Watermark from '@/utils/canvas/watermark' // js插件放置的 工具类目录
 * demo: <input class="upload-item-input" type="file"  accept="image/*" name="file" @change="PreviewImage(e)"/>
 * 使用示例: const newFile = e.target.files[0]
 * Watermark.addWatermark(file, watermarkData, function(base64Codes) {
      // console.log('callback-base64Codes', base64Codes)
      const blob = Watermark.convertBase64UrlToBlob(base64Codes)
      const { lastModified, type } = newFile
      const watermark_file = new File([blob], imgName, { type: type, lastModified: lastModified })
      // console.log('watermark_file', watermark_file)
      that.uploadImgObj.attachImgSrc = base64Codes // 加了水印 图片base64显示
      // that.upload(watermark_file, imgName) // 上传图片
    })
 * @param file imgFile
 * @param data:[item] 水印数列
 * @param callback 回调
 * @item { font, fillStyle, fillText, position } 单个水印
 * @font font: '20px 黑体', 水印字体设置
 * @fillStyle fillStyle: 'rgba(255,255,255,0.5)' rgba(255,255,255,0.5) or #f00
 * @fillText fillText: '我是文案'
 * @position position: { horizontal, horizontalMargin, vertical, verticalMargin } 定位位置
 * @data 传入的示例数组数据结构 this.watermarkData = [
 {
   font: '20px 黑体',
   fillStyle: '#fff',
   fillText: '2018-07-06 星期五 江西省xxxxx',
   position: {
     horizontal: 'center', // 水平方向居 (left,right,center)
     horizontalMargin: '0', // 水平方向居 margin
     vertical: 'bottom', // 垂直方向居 (top,bottom,middle)
     verticalMargin: '20' // 垂直方向居 margin
   }
 },
 {
   font: '40px 黑体',
   fillStyle: '#fff',
   fillText: '我是文案2',
   position: {
     horizontal: 'center', // 水平方向居 (left,right,center)
     horizontalMargin: '0', // 水平方向居 margin
     vertical: 'bottom', // 垂直方向居 (top,bottom,middle)
     verticalMargin: '46' // 垂直方向居 margin
   }
 }
 ]
 */
export function addWatermark(file, data, callback) {
  var ready = new FileReader()
  /* 开始读取指定的Blob对象或File对象中的内容. 当读取操作完成时,readyState属性的值会成为DONE,如果设置了onloadend事件处理程序,则调用之.同时,result属性中将包含一个data: URL格式的字符串以表示所读取文件的内容.*/
  ready.readAsDataURL(file) // 调用reader.readAsDataURL()方法,把图片转成base64
  ready.onload = function() {
    var re = this.result
    canvasDataURL(re, data, callback)
  }
}

function canvasDataURL(path, data, callback) {
  const watermarkData = data
  const img = new Image()
  img.src = path
  img.onload = function() {
    const that = this
    // 默认按比例压缩
    let w = ''
    let h = ''
    const scale = that.width / that.height
    // 如果图片尺寸太大,当图片原尺寸宽度大于800 时,设置新图片 宽度为800 ,高度并等比例缩放
    if (that.width > 800) {
      w = 800
      h = w / scale
    } else {
      w = that.width
      h = that.height
    }
    // 生成canvas
    const canvas = document.createElement('canvas')
    const ctx = canvas.getContext('2d')
    // 创建属性节点
    const anw = document.createAttribute('width')
    anw.nodeValue = w
    const anh = document.createAttribute('height')
    anh.nodeValue = h
    canvas.setAttributeNode(anw)
    canvas.setAttributeNode(anh)
    ctx.drawImage(that, 0, 0, w, h)
    // 需要加的水印数组
    for (const f in watermarkData) {
      const item = watermarkData[f]
      // console.log('canvasDataURL()-item', item)
      ctx.font = item.font
      ctx.fillStyle = item.fillStyle
      // 计算绘制水印的位置
      // const itemHorizontalPadding = 0 || f * item. // 主要用于 多个水印之间 垂直方向的间隔
      let positionX = 0
      let positionY = 0
      let textAlign = ''
      // 水平方向
      switch (item.position.horizontal) {
        case 'left':
          positionX = item.position.horizontalMargin
          textAlign = 'left'
          break
        case 'right':
          positionX = w - item.position.horizontalMargin
          textAlign = 'right'
          break
        case 'center':
          positionX = w / 2
          textAlign = 'center'
      }
      let textBaseline = ''
      // 垂直方向
      switch (item.position.vertical) {
        case 'top':
          positionY = item.position.verticalMargin
          textBaseline = 'top'
          break
        case 'bottom':
          positionY = h - item.position.verticalMargin
          textBaseline = 'bottom'
          break
        case 'middle':
          positionY = h / 2
          textBaseline = 'middle'
      }
      ctx.textAlign = textAlign // 水平居中
      ctx.textBaseline = textBaseline // 垂直居中
      ctx.fillText(item.fillText, positionX, positionY)
    }
    // 回调函数返回base64的值
    const base64 = canvas.toDataURL('image/jpeg', 1)
    callback(base64)
  }
}

/**
 * 将以base64的图片url数据转换为Blob
 * @param urlData
 * 用url方式表示的base64图片数据
 */
export function convertBase64UrlToBlob(urlData) {
  const arr = urlData.split(',')
  const mime = arr[0].match(/:(.*?);/)[1]
  const bstr = atob(arr[1])
  let n = bstr.length
  const u8arr = new Uint8Array(n)
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n)
  }
  return new Blob([u8arr], { type: mime })
}

 

 类似资料: