微信公众号H5拍照添加时间水印并上传-vue3

262 阅读2分钟

前置

以下为功能完整实现代码

<script setup>
import { fabric } from 'fabric'
import dayjs from 'dayjs'
const imageUrl = ref('') //微信拍照生成的base64存放路径
const previewImageUrl = ref('') //生成时间水印后预览路径
const displayImgRef = shallowRef()
const base64UrlByIosWithAndroid = (url) => {
  let localData = url
  if (localData.indexOf('data:image') != 0) {
    //判断是否有这样的头部
    localData = 'data:image/jpeg;base64,' + localData
  }
  imageUrl.value = localData
    .replace(/\r|\n/g, '')
    .replace('data:image/jgp', 'data:image/jpeg')
}
const dataURLtoFile = (dataurl, filename) => {
  //将base64转换为文件,dataurl为base64字符串,filename为文件名(必须带后缀名,如.jpg,.png)
  var arr = dataurl.split(','),
    mime = arr[0].match(/:(.*?);/)[1],
    bstr = atob(arr[1]),
    n = bstr.length,
    u8arr = new Uint8Array(n)
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n)
  }
  return new File([u8arr], filename, { type: mime })
}
const addMark = () => {
  displayImgRef.value.onload = () => {
    // 微信拍照展示图片加载完成
    const imgEl = displayImgRef.value
    const canvasEl = document.createElement('canvas')
    const scale = 0.5 //图片缩放倍数
    let imgInstance = new fabric.Image(imgEl, {
      left: 0,
      top: 0
    })
    let textEl = new fabric.IText(dayjs().format('YYYY年MM月DD日 HH:mm:ss'), {
      left: 60,
      top: 20,
      fontSize: 30,
      fill: 'white',
      fontFamily: 'Source Han Sans CN-Regular'
    })

    let canvas = new fabric.Canvas(canvasEl, {
      width: imgInstance.width * scale,
      height: imgInstance.height * scale
    })
    imgInstance.scaleX = scale
    imgInstance.scaleY = scale
    canvas.add(imgInstance)
    canvas.add(textEl)
    canvas.renderAll()

    nextTick(async () => {
      const base64Url = canvas.toDataURL('image/png')
      // base64Url为添加水印后生成
      previewImageUrl.value = base64Url //该路径可展示生成水印后的图片
      const fileName = 'xxx.png'
      const file = dataURLtoFile(base64Url, fileName)
      // file为文件流,以下可写上传代码
      console.log(file)
    })
  }
}

const handleChooseImage = () => {
  wx.chooseImage({
    count: 1, //只拍一张
    sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
    sourceType: ['camera'], // 指定选择相机
    success: (res) => {
      wx.getLocalImgData({
        localId: res.localIds[0], // 图片的localID
        success: function (res) {
          let localData = res.localData // localData是图片的base64数据,可以用img标签显示
          base64UrlByIosWithAndroid(localData) //处理微信返回base64兼容IOS与Android
          nextTick(() => {
            addMark() //添加水印
          })
        }
      })
    }
  })
}
</script>
<template>
  <div @click="handleChooseImage">点击拍照</div>
  <!-- 此图片为展示微信拍照后的图,可设置位置隐藏 -->
  <img ref="displayImgRef" :src="imageUrl" />
  <!-- 此图片为展示添加水印后的图 -->
  <img :src="previewImageUrl" />
</template>
<style lang="less" scoped></style>

有不明白的可以在评论区讨论~