效果如图
// 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]"
/>