微信小程序自定义分享
微信小程序自定义分享
1.使用canvas绘制自定义分享的图片。封装了常用的画图片,画线,画文字,画矩形等方法。
import shareBgImg from '@/static/image/share/share_bg.png' import shareLogo from '@/static/image/share/share_logo.png' import shareArrow from '@/static/image/share/share_arrow.png' /** * 绘制图片 * @param {*} param0 * canvas为微信小程序的canvas对象 */ const drawImage = ({ canvas, width, height, x = 0, y = 0, src }) => { return new Promise((resolve, reject) => { const img = canvas.createImage() img.src = src img.onload = () => { canvas.getContext('2d').drawImage(img, x, y, width, height) resolve() } img.onerror = ()=>{ resolve() } }) } /** * 绘制文本 * @param {*} param0 */ const drawText = ({ ctx, text, color = '#000', fontSize = 12, x, y }) => { ctx.fillStyle = color ctx.textBaseline = 'top' ctx.font = `${fontSize}px PingFangSC-Semibold, PingFang SC` ctx.fillText(text, x, y) } const drawRoundRectPath = ({ ctx, width, height, radius }) => { ctx.beginPath(0) //从右下角顺时针绘制,弧度从0到1/2PI ctx.arc(width - radius, height - radius, radius, 0, Math.PI / 2) //矩形下边线 ctx.lineTo(radius, height) //左下角圆弧,弧度从1/2PI到PI ctx.arc(radius, height - radius, radius, Math.PI / 2, Math.PI) //矩形左边线 ctx.lineTo(0, radius) //左上角圆弧,弧度从PI到3/2PI ctx.arc(radius, radius, radius, Math.PI, (Math.PI * 3) / 2) //上边线 ctx.lineTo(width - radius, 0) //右上角圆弧 ctx.arc(width - radius, radius, radius, (Math.PI * 3) / 2, Math.PI * 2) //右边线 ctx.lineTo(width, height - radius) ctx.closePath() } /**绘制有填充色的圆角矩形 *@param ctx:canvas的上下文环境 *@param x:左上角x轴坐标 *@param y:左上角y轴坐标 *@param width:矩形的宽度 *@param height:矩形的高度 *@param radius:圆的半径 *@param fillColor:填充颜色 **/ const drawFillRoundRect = ({ ctx, x, y, width, height, radius, fillColor }) => { //圆的直径必然要小于矩形的宽高 if (2 * radius > width || 2 * radius > height) { return false } ctx.save() ctx.translate(x, y) //绘制圆角矩形的各个边 drawRoundRectPath({ ctx, width, height, radius }) ctx.fillStyle = fillColor || '#000' //若是给定了值就用给定的值否则给予默认值 ctx.fill() ctx.restore() } /** * 画虚线 * * @param color 填充色 * @param startX 开始点的x坐标 * @param startY 开始点的y坐标 * @param endX 结束点的x坐标 * @param endY 结束点的y坐标 * * */ const drawDashedLine = ({ ctx, color = '#D8D8D8', lineWidth = 2, startX, startY, endX, endY, dashArray = [8, 8], }) => { ctx.lineWidth = lineWidth ctx.strokeStyle = color ctx.beginPath() ctx.setLineDash(dashArray) // 两个值为实处的宽度和虚处的宽度,为数组 ctx.moveTo(startX, startY) ctx.lineTo(endX, endY) ctx.stroke() } /** * 单行文本超出省略 * @param {*} text * @param {*} limit * @returns */ const ellipsisText = (text,limit=20) =>{ if(!text) return '' if(text.length>limit){ return `${text.substring(0,limit)}...` }else{ return text } } /** * 生成本地暂存图片路径 * @returns */ const canvasToTempFilePath = (canvas) => { return new Promise((resolve, reject) => { // 生成图片 wx.canvasToTempFilePath({ canvas, success: (res) => { // 生成的图片临时文件路径 const tempFilePath = res.tempFilePath resolve(tempFilePath) }, fail: (err) => { console.log(err) reject(err) }, }) }) } /** * 格式化日期 * @param {*} date */ const formatDate = (date) => { const time = new Date(date) return `${time.getFullYear()}年${time.getMonth()}月${time.getDate()}日${time.getHours()<10?`0${time.getHours()}`:time.getHours()}:${time.getMinutes()<10?`0${time.getMinutes()}`:time.getMinutes()}` } /** * 绘制自定义分享图片 * @param {*} data * @returns */ export const initShareCanvas = (data) => { if (!data) { return } return new Promise((resolve, reject) => { wx.createSelectorQuery() .select('#myCanvas') // 在 WXML 中填入的 id .fields({ node: true, size: true }) .exec(async (res) => { const { waybillNo, startPoint, arrivalPoint, arrivalTime, message, routeTime, } = data // Canvas 对象 const canvas = res[0].node // 渲染上下文 const ctx = canvas.getContext('2d') // Canvas 画布的实际绘制宽高 const width = res[0].width const height = res[0].height // 初始化画布大小 const dpr = wx.getWindowInfo().pixelRatio canvas.width = width * dpr canvas.height = height * dpr ctx.scale(dpr, dpr) // 清空画布 ctx.clearRect(0, 0, width, height) // 绘制背景图 const bgSrc = shareBgImg await drawImage({ canvas, width, height, x: 0, y: 0, src: bgSrc, }) // 绘制logo const logoSrc = shareLogo await drawImage({ canvas, width: 203, height: 47, x: 26, y: 48, src: logoSrc, }) // 绘制圆角矩形 drawFillRoundRect({ ctx, width: 484, height: 260, x: 8, y: 130, radius: 8, fillColor: '#fff', }) // 绘制文字:出发地 drawText({ ctx, text: startPoint, x: 56, y: 160, fontSize: 32, color: '#1C253B', }) // 绘制箭头 const arrowSrc = shareArrow await drawImage({ canvas, width: 102, height: 17, x: 190, y: 168, src: arrowSrc, }) // 绘制文字:到达地 drawText({ ctx, text: arrivalPoint, x: 340, y: 160, fontSize: 32, color: '#1C253B', }) // 绘制文字:运单号 drawText({ ctx, text: `运单号:${waybillNo}`, x: 94, y: 215, fontSize: 24, color: '#606675', }) // 绘制虚线 drawDashedLine({ ctx, color: '#D8D8D8', startX: 32, startY: 264, endX: 468, endY: 264, }) // 绘制预计到达时间文本 if (arrivalTime) { drawText({ ctx, text: `预计${formatDate(arrivalTime)}前送达`, x: 32, y: 282, fontSize: 20, color: '#A4A8B1', }) } // 绘制提示消息 drawText({ ctx, text: ellipsisText(message), x: 32, y: 320, fontSize: 20, color: '#A4A8B1', }) // 绘制路由的发生时间 drawText({ ctx, text: routeTime, x: 32, y: 356, fontSize: 20, color: '#A4A8B1', }) // 最终生成文件地址 const imageurl = await canvasToTempFilePath(canvas) console.log(imageurl) resolve(imageurl) }) }) }
2.小程序配置分享
// 配置微信分享 onShareAppMessage(async () => { // 初始化canvas let data = { waybillNo: '', // 运单号 startPoint: '', // 出发地 arrivalPoint: '', // 到达地 arrivalTime: '', // 预计到达时间 message: '', // 消息提示 routeTime: '', // 路由的发生时间 } // canvas的mock数据 try { const { result } = await apiGetShareInfo(waybillId.value) data = result } catch (error) { // 出错使用默认的数据 } // 生成本地临时图片url并分享 const imageUrl = await initShareCanvas(data) console.log(imageUrl) return { title: '快递正向您飞奔,点击了解哦~', path: `/scanPrint/searchExpress/routeDetail/routeDetail?waybillId=${waybillId.value}&from=share`, imageUrl: imageUrl, } })
效果如图: