微信小程序自定义分享

微信小程序自定义分享

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,
            }
        })

效果如图:

posted @ 2023-10-08 15:03  wayne529  阅读(152)  评论(0编辑  收藏  举报