小程序canvas绘制自定义分享图片并分享给好友

小程序的分享有自己的机制,在页面点击右上角,或者页面中的button 采用open-type=share方式也可以触发onShareAppMessage方法。
小程序canvas绘制自定义分享图片并分享给好友_第1张图片
文档里面明确说明,分享的图片可以采用网络图片,那么我们自定义图片之后将其保存,得到微信的临时文件路径也是符合要求的。
废话不多说,直接贴代码。我将绘制分享图的功能封装了一下,如下:

// 考虑了有些文字是带有换行符的,安卓和iOS对于换行符的处理不一样,所以这里需要单独考虑
// canvas绘制文字自动换行
function fillTextToCanvas(cxt, text, beginWidth, beginHeight) {
    const lineLength = 24;// 行高
    let item = '';
    let count = 0;
    const stringLength = text.length;
    const newText = text.split('');
    const context = cxt;
    let beginHeightNew = beginHeight;
    context.textAlign = 'left';
    for (let i = 0; i <= stringLength; i++) {
        if (count === 15) { // count一行显示多少个字
            context.fillText(item, beginWidth, beginHeightNew);
            beginHeightNew += lineLength;
            item = '';
            count = 0;
        }
        if (i === stringLength) {
            context.fillText(item, beginWidth, beginHeightNew);
            item = '';
            count = 0;
        }
        item += newText[0];
        count += 1;
        newText.shift();
    }
}
//  canvas绘制文字自动换行
function drawLongText(longText, cxt, beginWidth, beginHeight) {
    const lines = longText.split('\n');
    const linesLen = lines.length;
    const lineLength = 24;// 行高
    if (linesLen >= 0) {
        for (let t = 0; t < linesLen; t++) {
            const beginHeightNew = beginHeight + lineLength * t;
            fillTextToCanvas(cxt, lines[t], beginWidth, beginHeightNew);
        }
    }
}

// 绘制分享图片
function createSharePicUrl(self, avatar, nickname, college, content, callback) {
    const shareCtx = wx.createCanvasContext('shareCanvas', self);
    shareCtx.rect(0, 0, 250, 200);
    shareCtx.setFillStyle('white');
    // 画头部个人信息
    wx.downloadFile({
        url: avatar,
        success(res) {
            const avatarWidth = 40; // 绘制的头像宽度
            const avatarHeight = 40; // 绘制的头像高度
            const avatarX = 12; // 绘制的头像在画布上的位置
            const avatarY = 15; // 绘制的头像在画布上的位置
            shareCtx.save();
            shareCtx.beginPath(); // 开始绘制
            // 先画个圆   前两个参数确定了圆心 (x,y) 坐标  第三个参数是圆的半径  四参数是绘图方向  默认是false,即顺时针
            shareCtx.arc(avatarWidth / 2 + avatarX,
                avatarHeight / 2 + avatarY,
                avatarWidth / 2,
                0,
                Math.PI * 2,
                false);
            shareCtx.clip();
            shareCtx.drawImage(res.tempFilePath,
                avatarX, avatarY,
                avatarWidth,
                avatarHeight); // 推进去图片,必须是https图片
            shareCtx.restore(); // 恢复之前保存的绘图上下文 恢复之前保存的绘图上下午即状态 还可以继续绘制
            // 画中间帖子内容
            shareCtx.setTextAlign('left'); // 文字居中
            shareCtx.setFillStyle('#333333');
            shareCtx.setFontSize(15); // 文字字号:15px
            shareCtx.fillText(nickname, 64, 31, 100);
            shareCtx.setFillStyle('#999999');
            shareCtx.setFontSize(12); // 文字字号:12px
            shareCtx.fillText(college, 64, 52, 100);
            shareCtx.setFillStyle('#070707');
            shareCtx.setFontSize(15); // 文字字号:15px
            drawLongText(content, shareCtx, avatarX, 75 + 10);
            shareCtx.draw(false, setTimeout(callback, 200));
        },
    });
}
module.exports = {
    drawLongText,
    createSharePicUrl,
};

上面我将两个方法也都暴露出来了,可以在每个页面自由的调用。
调用方法:

// 在xx.js里面引入
const createSharePic = require('../../utils/createSharePic');

生成分享图之后,将图片保存,生成分享图,方便分享。

createSharePic.createSharePicUrl(this,
    item.avatar,
     item.nickname,
     item.collegeName,
     item.body, () => {
     wx.canvasToTempFilePath({
         canvasId: 'shareCanvas',
         x: 0,
         y: 0,
         width: 250,
         height: 200,
         success(res) {
             console.log(res.tempFilePath);
             that.setData({
                 sharePicUrl: res.tempFilePath,
             });
         },
     }, that);
 });

下面简述了一下我本次开发遇到的问题,有兴趣的可以看下,也许你也出现了同样的问题,这样我们也算同病相怜,哈哈哈~

遇到的问题:

  • 问题1:canvas层级问题
    canvas是原生组件,在所有的组件的上面,除非你用cover-view组件,但是那个更坑爹,看到下面bug&tip那么多,我瞬间觉得难用,用了之后发现果然难用,所以我直接放弃了这个组件。
    小程序canvas绘制自定义分享图片并分享给好友_第2张图片
    那到底怎么解决这个层级的问题呢?
  1. 必要的时候再显示,不必要的时候隐藏
    wx:if可以控制一个组件的显示和隐藏,这个方法可以参考下。比如我之前的场景:某个页面有多个弹框,弹框出现的时候,绘制的canvas的图会显示在最上面,弹框盖不住那个图,这个时候,我发现将canvas图隐藏起来,弹框能正常显示,那就隐藏呗。哈哈哈,因为我的弹框很大,canvas图片隐藏之后用户也是感知不大的,弹框消失的时候再显示,完美~哈哈哈

  2. 移到窗口看不到的地方
    这是我这次采用的方法。position:fixed; right:-100%; css里面添加两个属性,这样canvas就在窗口外面啦,可能此时canvas就会说:小伙砸,看不到我,看不到我,我就在这里,来抓我呀~~哈哈哈

  • 问题2:创建分享图的时机
    创建分享图是这次功能实现花时比较多的点,我的场景是这样的:页面里面有一个列表,列表里面的每一项都可以分享,也可以删除,这里的分享需要走原生onShareMessage方法,分享图里面需要多个元素,也就是分享的内容需要自定义。
    (1)原来我的想法是:点击买个item的时候我再去绘制图片,等到分享图绘制好了之后我再显示分享卡片,但是我发现每次分享的卡片显示了之后,我的图还没绘制好,捶你的小胸口~~我要哭会。
    (2)看来这个思路不行啊,容我开动下脑筋,想个新方法。那就先将每个item对应的分享图绘制好,然后点击item的时候将对应的分享图保存下面给分享卡片,这么一测试,我发现,哎,好像可以啦。但是当我测试了删除和新增功能之后,我就又蛋疼了,因为新增的没有生成新的对应的canvas,删除之后呢,canvas也没有相应的删除,导致分享卡片跟内容不对应的问题,我勒个去的,捶你的小胸口,我再哭会~。
    (3)上面两个方法都不行,我觉得我需要苦思冥想一下,于是我出去上个了厕所…嗯,想出来了,那就保证永远都是一个canvas,每次在这个画布上面重新绘制分享图。为了防止又出现之前分享图来不及绘制的问题,这次实现思路是这样的:点击每个item的时候我就开始绘制,并将生成的图片保存起来,然后再让分享按钮显示,分享按钮是下面这样的:
    小程序canvas绘制自定义分享图片并分享给好友_第3张图片
    点击分享的时候,去拿刚刚生成的分享图的临时链接,你会发现成啦。生成的分享卡片内容是一致的,而且新增,删除之后也不会错乱,啊哈哈哈,让小姐姐我长舒一口气。
    小程序canvas绘制自定义分享图片并分享给好友_第4张图片
    (4)有的图片不显示
    这次我需要显示的头像,或者你需要一些其他的图片,这些图片你需要先下载下来,不然就会不显示。
    顺便赘述下:因为小程序的分享卡片图片是5:4比例,所以这里我直接写死了在方法里面,各位如果有其他的需要可以自行更改,每个元素的位置也是可以自己调哒,么么哒,分享给你们,希望对大家有用。

你可能感兴趣的:(开发技能,js,前端,小程序)