uniapp纯前端绘制商品分享图

发布于:2025-08-16 ⋅ 阅读:(11) ⋅ 点赞:(0)

效果如图
在这里插入图片描述

// useMpCustomShareImage.ts

interface MpCustomShareImageData {
  canvasId: string
  price: string
  linePrice: string
  goodsSpecFirmName: string
  image: string
}

const CANVAS_WIDTH = 500
const CANVAS_HEIGHT = 400
const BG_IMAGE = 'https://public-scjuchuang.oss-cn-chengdu.aliyuncs.com/goods_share.png'
const DEFAULT_IMAGE =
  'https://public-scjuchuang.oss-cn-chengdu.aliyuncs.com/mini_program/mp_default_sc.png'

const loadImageInfo = (src: string): Promise<UniApp.GetImageInfoSuccessData> => {
  return new Promise((resolve, reject) => {
    uni.getImageInfo({
      src,
      success: resolve,
      fail: reject,
    })
  })
}

// 绘制价格
const loadPrice = (ctx: any, text: string, x: number, y: number) => {
  ctx.font = `bold ${text.length >= 10 ? '32px' : '36px'} sans-serif`
  ctx.setFillStyle('#e2231a')
  ctx.setTextAlign('center')
  ctx.setTextBaseline('middle')

  ctx.fillText(text, x, y)
}

// 绘制划线价
const loadLinePrice = (ctx: any, text: string, x: number, y: number) => {
  ctx.font = '20px sans-serif'
  ctx.setFillStyle('#999999')
  ctx.fillText(text, x, y)

  const metrics = ctx.measureText(text)
  ctx.strokeStyle = '#999999'
  ctx.lineWidth = 2
  const textWidth = metrics.width

  ctx.beginPath()
  ctx.moveTo(x - textWidth / 2, y)
  ctx.lineTo(x + textWidth / 2, y)
  ctx.stroke()
}

// 绘制规格厂家
const loadGoodsSpecFirmName = (ctx: any, text: string, y: number) => {
  const maxWidth = 480
  ctx.font = '20px sans-serif'
  ctx.setFillStyle('#333')

  // 短文字
  const textWidth = ctx.measureText(text).width
  if (textWidth <= maxWidth) {
    return ctx.fillText(text, CANVAS_WIDTH / 2, y)
  }

  // 长文字,省略显示
  const displayText = text.substring(0, 21) + '...'
  ctx.fillText(displayText, CANVAS_WIDTH / 2, y)
}

const useMpCustomShareImage = () => {
  const set = async (data: MpCustomShareImageData): Promise<string> => {
    const { canvasId, price, linePrice, goodsSpecFirmName, image = DEFAULT_IMAGE } = data
    const imageWidth = 250
    const imageHeight = 250

    try {
      const ctx = uni.createCanvasContext(canvasId, this)

      const [bgImageInfo, imageInfo] = await Promise.all([
        loadImageInfo(BG_IMAGE),
        loadImageInfo(image),
      ])

      // 绘制背景图
      ctx.drawImage(bgImageInfo.path, 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT)
      // 绘制商品图
      ctx.drawImage(imageInfo.path, 20, 80, imageWidth, imageHeight)
      // 绘制价格
      loadPrice(ctx, price, CANVAS_WIDTH - imageWidth / 2, 150)
      // 绘制划线价
      loadLinePrice(ctx, linePrice, CANVAS_WIDTH - imageWidth / 2, 200)
      // 绘制规格厂家
      loadGoodsSpecFirmName(ctx, goodsSpecFirmName, 360)

      // 绘制
      await new Promise<void>((resolve) => {
        ctx.draw(false, resolve)
      })

      // 生成分享图
      const { tempFilePath } = await new Promise<UniApp.CanvasToTempFilePathRes>(
        (resolve, reject) => {
          uni.canvasToTempFilePath({
            canvasId,
            success: resolve,
            fail: reject,
          })
        },
      )

      return tempFilePath
    } catch (error) {
      console.error('生成分享图失败:', error)
      return image
    }
  }

  return { set }
}

export default useMpCustomShareImage

// 调用

import useMpCustomShareImage from './useMpCustomShareImage'

const mpCustomShareImage = useMpCustomShareImage()

mpCustomShareImage.set({
  canvasId: 'shareCanvas',
   price: `¥4.60/盒`,
   linePrice: `¥4.73/盒`,
   goodsSpecFirmName: `0.25g*50粒 重庆科瑞制药(集团)有限公司`,
   image:
     'https://public-scjuchuang.oss-cn-chengdu.aliyuncs.com/mini_program/mp_default_sc.png',
 })
 .then((img) => {
   // 分享图
   console.log(img)
 })


// -left-[1000px] -top-[1000px] 要放在页面上,且不显示
<canvas
  canvasId="shareCanvas"
  class="w-[500px] h-[400px] absolute -left-[1000px] -top-[1000px]"
/>

网站公告

今日签到

点亮在社区的每一天
去签到