美文网首页
vue 用户信息生成分享海报

vue 用户信息生成分享海报

作者: DeadMoon | 来源:发表于2021-10-18 18:01 被阅读0次

需要使用的地方: new GeneratePoster({ qrUrl, companyName, userImg, userName, tips }).start()

const ERR_CODE_ENUM = {
  CODE_ERROR: '加载二维码失败',
  USER_IMG_ERROR: '加载头像失败'
}

const { clientWidth } = document.body
const DESIGN_WIDTH = 750
const SHANG = clientWidth / DESIGN_WIDTH
const CANVAS_SIZE = {
  // eslint-disable-next-line no-mixed-operators
  width: 670 * SHANG,
  // eslint-disable-next-line no-mixed-operators
  height: 750 * SHANG
}
// 用户头像
const USER_IMG = {
  top: 20 * SHANG,
  left: 20 * SHANG,
  width: 100 * SHANG,
  height: 100 * SHANG
}
const QR_IMG = {
  top: 140 * SHANG,
  left: 20 * SHANG,
  width: 512 * SHANG,
  height: 512 * SHANG
}
// 用户名字
const USER_NAME = {
  size: 28 * SHANG,
  top: 25 * SHANG,
  left: 140 * SHANG,
  color: '#333333'
}
// 企业名称
const COMPANT_NAME = {
  size: 24 * SHANG,
  top: 90 * SHANG,
  left: 140 * SHANG,
  color: 'rgba(51, 51, 51, 0.8)'
}
// 底部提示
const TIP_TEXT = {
  size: 24 * SHANG,
  top: 700 * SHANG,
  left: 140 * SHANG,
  color: '#000'
}
// eslint-disable-next-line no-unused-vars
class GeneratePoster {
  constructor(param = {}) {
    this.qrUrl = param.qrUrl
    this.userName = param.userName || ''
    this.userImg = param.userImg || ''
    this.companyName = param.companyName || ''
    this.tips = param.tips
  }

  async createCanvas() {
    // eslint-disable-next-line func-names
    const getPixelRatio = function (context) {
      const backingStore = context.backingStorePixelRatio || context.webkitBackingStorePixelRatio || context.mozBackingStorePixelRatio || context.msBackingStorePixelRatio || context.oBackingStorePixelRatio || context.backingStorePixelRatio || 1
      return (window.devicePixelRatio || 1) / backingStore
    }
    const canvasEl = document.createElement('canvas')
    const ctx = canvasEl.getContext('2d')
    const ratio = getPixelRatio(ctx)
    canvasEl.style.width = `${CANVAS_SIZE.width}px`
    canvasEl.style.height = `${CANVAS_SIZE.height}px`
    canvasEl.width = CANVAS_SIZE.width * ratio
    canvasEl.height = CANVAS_SIZE.height * ratio
    ctx.fillStyle = '#fff'
    ctx.fillRect(0, 0, canvasEl.width, canvasEl.height)
    ctx.scale(ratio, ratio)
    return { ctx, canvasEl }
  }

  /**
   * @desc 客户二维码
   * @param ctx
   * @private
   */
  _drawQrCode(ctx) {
    return new Promise((resolve, reject) => {
      const imgEl = document.createElement('img')
      imgEl.setAttribute('crossOrigin', 'Anonymous')
      imgEl.src = this.qrUrl
      imgEl.onload = () => {
        ctx.drawImage(imgEl, (CANVAS_SIZE.width - QR_IMG.width) / 2, QR_IMG.top, QR_IMG.width, QR_IMG.height)
        resolve()
      }
      imgEl.onerror = (err) => {
        console.log(err)
        reject(ERR_CODE_ENUM.CODE_ERROR)
      }
    })
  }

  /**
   * 开始画二维码说明
   * @param ctx
   * @private
   */
  async _drawTipsText(ctx) {
    ctx.textBaseline = 'bottom'
    ctx.font = `${TIP_TEXT.size}px bold`
    ctx.fillStyle = TIP_TEXT.color
    ctx.fillText(this.tips, TIP_TEXT.left, TIP_TEXT.top)
  }

  /**
   * @desc 客户昵称
   * @param ctx
   * @private
   */
  async _drawNickname(ctx) {
    ctx.textBaseline = 'top'
    ctx.font = `${USER_NAME.size}px bold`
    ctx.fillStyle = USER_NAME.color
    ctx.fillText(this.userName, USER_NAME.left, USER_NAME.top)
  }

  /**
   * @desc 用户公司名称
   * @param ctx
   * @private
   */
  _drawCompanyName(ctx) {
    ctx.textBaseline = 'top'
    ctx.font = `${COMPANT_NAME.size}px bold`
    ctx.fillStyle = COMPANT_NAME.color
    ctx.fillText(this.companyName, COMPANT_NAME.left, COMPANT_NAME.top)
  }

  /**
   * 画用户头像
   * @param ctx
   * @private
   */
  _drawUserImg(ctx) {
    return new Promise((resolve, reject) => {
      const imgEl = document.createElement('img')
      imgEl.setAttribute('crossOrigin', 'Anonymous')
      imgEl.src = this.userImg
      imgEl.onload = function () {
        ctx.drawImage(imgEl, USER_IMG.left, USER_IMG.top, USER_IMG.width, USER_IMG.height)
        resolve()
      }
      imgEl.onerror = () => {
        reject(ERR_CODE_ENUM.USER_IMG_ERROR)
      }
    })
  }

  async start() {
    try {
      const { ctx, canvasEl } = await this.createCanvas()
      await this._drawUserImg(ctx)
      await this._drawNickname(ctx)
      await this._drawCompanyName(ctx)
      await this._drawQrCode(ctx)
      await this._drawTipsText(ctx)
      return canvasEl.toDataURL('image/png')
    } catch (e) {
      console.error(e)
    }
  }
}

export default GeneratePoster

相关文章

网友评论

      本文标题:vue 用户信息生成分享海报

      本文链接:https://www.haomeiwen.com/subject/vcmnoltx.html