专栏首页IMWeb前端团队微信小程序之分享海报生成

微信小程序之分享海报生成

本文作者:IMWeb 结一 原文出处:IMWeb社区 未经同意,禁止转载

为了吸引更多的用户,设计好一个分享海报还是很有必要的。而小程序要生成一个海报还是有点坑的,下面分享下我们打卡小程序的一些经验。

分享海报的效果图如下:

制作要求:

  • 海报以弹窗形式展现,各种手机型号都可以正常显示
  • 海报的内容由背景图、日期、随机的名言警句、活动的二维码及用户的参加活动的信息
  • 海报保存的图片大小为 iphone 6 的两倍图(750 * 1334)

由于看到的弹窗图片与保存的图片是两种大小,所以一开始看了些网上的其他教程,建议是搞两个 canvas 一个大的一个小的。实际过程中,采用了一个大的 canvas ,让其偏离视窗显示区域(不可见)并生成临时文件,弹窗的图片再使用 img 组件,引入临时文件,设置其高度;而保存的时候则直接下载临时文件。

虽然是实现了,但是后来在优化的过程中,这个方案也重新设计了。下面具体介绍下优化过的方案:

  • 优先使用一个 canvas 绘制二维码;
  • 弹窗的图片即为一个 canvas;
  • 分享的图片为该 canvas 导出的大图片;
  • 为了达到最佳效果,名言警句的换行录入时就处理好。

设计弹窗的图片比例

由于最后海报的图片大小为 iphone 8 的两倍图(750 * 1334),所以这里弹窗的图片也即是 canvas 的大小,设计为对应的尺寸的某个比例。

弹窗图片的高度 = 视窗的高度 - 上下留白 - 按钮的高度 - 图片与按钮的距离
弹窗图片的高度 = 100vh - 40rpx * 2 - 50rpx - 15rpx

// iPhone 8 的尺寸标准为 750px * 1334px
弹窗图片的宽度 /  弹窗图片的高度 = 750 / 1334
弹窗图片的宽度 = (750 / 1334) * 弹窗图片的高度

由于像素只能是整数,所以这样绘制出来的图片可能底部会有1px的空白,所以在设置高度的时候可以再减掉 1px,这不会影响视觉效果。

绘制背景图

如果是网络图片,绘制背景图之前一定要先下载该图片,可通过 wx.getImageInfowx. downloadFile 下载图片,下载成功后将其塞进临时地址,然后使用 wx canvas 的 drawImage 绘制。注意如果地址是 base64 的话, gif 是不行的。

// 预先下载图片
preLoadImg(url, taskId) {
    url = /^https/.test(url) ? url : `https:${url}`;
    wx.getImageInfo({
      src: url,
      success(res) {
        // 把图片存下
        app.globalData[`tempImg${taskId}`] = res.path;
      },
      fail(err) {
        console.log(err);
      },
    });
  },

绘制二维码

绘制二维码换了好几个库,每个在安卓下面生成的二维码都会频现失败。查了好些资料,说是安卓绘制的时候要设置个 setTimeout,于是最终选择了weapp-qrcode,修改了其绘制的函数,增加了setTimeout(还真别说,加上二维码绘制就成功了)。

ctx.draw(false, function (e) {
    setTimeout(() => { // 修改增加的
        options.callback && options.callback(e)
    }, 20);
})

另:目前这些绘制小程序二维码的库都是在一个单独的新 canvas 中完成的,只要对源码稍作修改,就可以提供另一个接口,直接在一个现有的 canvas (表示 canvas 中一开始绘制了其他内容) 中绘制。

如果二维码扫不出来,则表示二维码绘制出了问题。但安卓微信 6.7.2 版本本身有个 bug,二维码本身是没有问题,它却不能识别。不过升级下微信版本就好了。

canvas 绘制完毕及下载

具体的绘制调用的都是 api,就不多说了。主要说下绘制完毕如何处理。先异步触发绘制完毕,该事件中将 canvas 显示出来,也即是小图。同时生成n倍分享图,并触发事件,该事件中将大图的缓存文件保存下来。然后到下载的时候使用。

// 绘制完毕处理
ctx.draw(false, async () => {
        // canvas 绘制好了触发 drawDone
        setTimeout(() => {
          this.triggerEvent('drawDone', this);
        }, 100);

        // 生成用于分享的图,pixelRatio 为 倍数
        const { canvasId, canvasWidth, canvasHeight, pixelRatio } = this.data;
        const { tempFilePath } = await wxCanvasToTempFilePath(
          {
            x: 0,
            y: 0,
            width: canvasWidth,
            height: canvasHeight,
            destWidth: canvasWidth * pixelRatio, // 导出大小为 canvas 的 pixelRatio 倍
            destHeight: canvasHeight * pixelRatio,
            canvasId,
          },
          this
        );
        // 生成分享图完毕触发
        this.triggerEvent('saveDone', tempFilePath);
});

// 下载处理
// 路径为上一步保存的分享图暂存图
wx.saveImageToPhotosAlbum({
      filePath: cardTempImgPath,
      success() {
        wx.showToast({
          title: '保存成功', // 提示的内容,
          icon: 'success', // 图标,
          duration: 2000, // 延迟时间,
          mask: true, // 显示透明蒙层,防止触摸穿透,
        });
      },
      fail(err) {
        console.log(err);
        wx.showToast({
          title: '保存失败', // 提示的内容,
          icon: 'none', // 图标,
          duration: 2000, // 延迟时间,
          mask: true, // 显示透明蒙层,防止触摸穿透,
        });
      },
    });

保存图片

  • 先要获取用户是否开启用户授权相册
  • 如果没有权限,则弹窗提示开通权限,如果有权限直接调用 saveImageToPhotosAlbum 接口保存图片
  • 如果弹窗提示接受开通权限,则调用 saveImageToPhotosAlbum 接口保存图片
  • 如果弹窗提示拒绝则再次弹窗是否去设置开通权限,如果是则进入设置权限
// 先尝试保存
trySaveImg() {
  const _this = this;
  // 获取用户是否开启用户授权相册
  wx.getSetting({
    success(res) {
      // 如果没有则获取授权
      if (!res.authSetting['scope.writePhotosAlbum']) {
        wx.authorize({
          scope: 'scope.writePhotosAlbum',
          success() {
            _this.saveImg();
          },
          fail() {
          // 如果用户拒绝过或没有授权,则再次打开授权窗口
          // (ps:微信api又改了现在只能通过button才能打开授权设置,以前通过openSet就可打开,下面有打开授权的button弹窗代码)
            wx.showModal({
              title: '获取权限失败',
              content: '是否打开设置页,允许小程序保存图片到你的相册',
              success: () => {
                wx.openSetting({
                  success (sRes) {
                    if (sRes.authSetting['scope.writePhotosAlbum']) {
                      setTimeout(() => {
                        _this.saveImg();
                      }, 200);
                    }
                  },
                });
              },
            });
          },
        });
      } else {
        // 有则直接保存
        _this.saveImg();
      }
    },
  });
},
// 正式保存
saveImg() {
  const { tempImgPath } = this.data;

  wx.showLoading({
    title: '正在保存中...', // 提示的内容,
    mask: true, // 显示透明蒙层,防止触摸穿透,
  });

  wx.saveImageToPhotosAlbum({
    filePath: tempImgPath,
    success() {
      wx.showToast({
        title: '保存成功',
        icon: 'success',
        duration: 2000,
        mask: true,
      });
    },
    fail() {
      wx.showToast({
        title: '保存失败', 
        icon: 'none',
        duration: 2000,
        mask: true,
      });
    },
  });
},

性能注意

经实践测试整个绘制过程其实还是很快的,但是如果有保存临时文件操作( wx.canvasToTempFilePath ),那么这个操作一般得占一半时间左右。除此之外,有个 measureText api,用来测量文字的长度,这个在实现自动换行的时候用得到,但是比较耗性能。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 利用canvas实现一个抠图小工具

    利用canvas实现一个抠图小工具 0 前言 作为新一代的前端开发工程师,PS抠图切图已经不是必备技能了,我们有UI/交互/视觉等更专业的设计同学帮我们做这个事...

    IMWeb前端团队
  • 利用canvas实现一个抠图小工具

    作为新一代的前端开发工程师,PS抠图切图已经不是必备技能了,我们有UI/交互/视觉等更专业的设计同学帮我们做这个事情。但是有时候还是有一些简单的图片处理工作需要...

    IMWeb前端团队
  • polymer组件化与vm特性

    Polymer是Google在2013年的Google I/O大会上提出了一个新的UI框架。Polymer的实现使用了WebComponent标准,并且Poly...

    IMWeb前端团队
  • Zimg—轻量级图片服务器搭建利器

    在一个互联网应用中,图片扮演着越来越重要的角色。有稳定的可扩展的图片存储服务器就显得尤为的重要,云厂商们提供了便利的图片存储服务,花钱就可以解决了。这里简单介绍...

    歪脖贰点零
  • 《最优图像优化》文件尺寸和质量之间选择完美平衡,适合摄影师使用的图片压缩工具

    这里推荐一款可视化的在线图片压缩工具,通过压缩曲线与预览图结合的方式,让你对压缩图片减少的体积有直观的感受,工具在本地浏览器运行,节省带宽,不泄露隐私,而且还免...

    zhaoolee
  • Martin Casado跳出网络圈回首SDN/IBN/API

    SDNLAB
  • hdu1047

    @坤的
  • 腾讯瞄准OpenDaylight,软件如何定义鹅厂

    加利福尼亚的圣克拉拉又迎来了一场大会——OpenDaylight峰会,在腾讯SDN分享中大会拉开了序幕。 腾讯为满足“各个方式的极限需求”构建了其SDN基础网...

    SDNLAB
  • KMP算法的原理和实现

    只要你学过数据结构与算法分析,相信你对KMP算法应该都不陌生吧?如果你没听过,不要紧,今天我们就来聊一聊这个算法。建议最好拿一张草稿纸,然后边看边理解,这样更有...

    xujjj
  • 对抗生成网络-文字到图片的合成Generative Adversarial Text to Image Synthesis

    新的一年,新的开始,好想发论文啊!废话不多说,下面讲下文字到图片的生成。 ? 文字生成图片 ? 最有代表的一张图怕是这个了,牛人,大佬 RNN可用来对文字进行判...

    水球喵子

扫码关注云+社区

领取腾讯云代金券