业务中碰到微信小程序需要生成海报进行朋友圈分享,这个是非常常见的功能,没想到实际操作的时候花了整整一天一夜才搞好,微信的 canvas 绘图实在是太难用了,官方快点优化一下吧。

业务非常简单,只需要将用到的图片,文案素材拼装到一张图片,保存到本地就可以了。

首先创建画布,将一张网上的图片画到画布上。

const ctx = wx.createCanvasContext('shareCanvas');
ctx.drawImage("https://img3.doubanio.com/view/photo/l/public/p2327709524.jpg", 0, 0, 300, 400);
ctx.draw();

网络图片

这时候出现一个问题:在模拟器上没有报错,可是真机测试却什么也没画出来。网上搜索一阵发现微信小程序的 canvas.drawImage 是不支持网络图片的,只支持本地图片。所以,任何的网络图片都需要先缓存到本地,再通过 drawImage 调用存储的本地资源进行绘制,缓存可以通过 wx.getImageInfo 和 wx.downloadFile 实现,这次选用了 wx.getImageInfo, wx.downloadFile 没有试过,不知道可不可以。

wx.getImageInfo({
src: 'https://img3.doubanio.com/view/photo/l/public/p2327709524.jpg',
success: function (res) {
console.log(res.width)
console.log(res.path)
}
})

这个方法可以拿到存储的本地图片地址,长宽以及一些简单的图形变化,将本地缓存的图片地址保存到全局变量或者缓存供 wx.drawImage 调用。

还有一点需要注意的是 draw 方法是异步的,如果图片还没加载成功,有可能画出来的是空的,所以 draw 方法通常都会带有定时器这样的回调。

ctx.draw(true,setTimeout(function(){
wx.canvasToTempFilePath({
canvasId: 'shareCanvas',
success: function(res){
that.data.tmpPath = res.tempFilePath
},
})
},1000));

图片保存的授权问题

绘图后通过 1 秒的延时将画好的新图片保存到本地,然后通过 wx.saveImageToPhotosAlbum() 保存到手机相册。这一步存在授权问题,需要考虑拒绝授权后的兼容性,也就是如果用户拒接授权以后怎么办?常见的做法是先通过 wx.getSetting() 获取用户的权限设置,如果用户拒绝了访问相册的权限,可以跳转到授权设置页面要求用户更改授权信息。

小程序的授权设置 api 已经弃用了,现在只能通过组件形式,将 button 的 open-type 属性设置成 openSetting,自动跳转到设置页面,总体来说没有之前方便了。如果页面本来已经有 button可以先将 open-type 属性设成 null,当遇到需要跳转的逻辑再通过 setData 设置,这样处理非常复杂,很容易出错,但是可以节省页面或者跳转;另一种处理方式是,当没有授权时先跳转到说明页面,说明需要授权的信息,在这个页面上添加一个 open-type 的button,点击以后跳转到设置页面,这次我们采用的是第一种方法:

文字编辑换行

下一步是文字编辑的问题,微信画文字是不支持自动换行的,所以只能手动计算每一行能够容纳的文字个数进行手动换行,比如一个文字加间距占 10 px,一行整体可以使用 100 px,那就是每行只能容纳 10 个字,第 11 个字另起一行开始画。

将文字分割成 10 个字的数组:

function canvasWorkBreak(maxWidth, fontSize, text) {
const maxLength = maxWidth / fontSize
const textLength = text.length
let textRowArr = []
let tmp = 0
while (1) {
textRowArr.push(text.substr(tmp, maxLength))
tmp += maxLength
if (tmp >= textLength) {
return textRowArr
}
}
}

将数组一行一行画到画布上:

var height = 200
for (let item of ['我的舍利佛','搜房法拉']) {
if (item !== 'a') {
ctx.setFontSize(16);
ctx.setFillStyle("#484a3d");
ctx.fillText(item, 20, height);
height += 50;
}
}

多图绘制

把每一种元素画完以后整个海报制作的流程就已经跑通了,但并不代表在实际业务中就可以使用了。首先面对的是海报生成的质量问题,假设我们的手机像素是 320 * 400 的,如果要将图片展示在手机上用于预览,只有两种选择:

  1. 画一个分辨率小于手机分辨率的海报,让手机能完整的展示出来。但是这样的海报由于分辨率小,下载到手机相册分享用大屏手机观看的时候就非常影响体验了。这种做法的解决方案可以是画 2 张图,手机预览时隐藏大图,只显示小图;下载的时候将大图保存起来。
  2. 画一张大图,直接通过 previewImage 进入手机预览模式,预览模式的图片可以直接保存到本地。这种方案的缺点在于预览模式无法设计 UI,且下载的时候不能自定义文案,由于下载保存的入口很隐蔽,用户不一定能发现。

图片太长怎么办?

上面的图实际上是比较长的,你可以截取一部分显示出来,这样图片看起来就会更协调。在通过正常比例绘制完图片以后,可以通过填充矩形的方式覆盖一部分图片,然后在矩形上输入其他的内容,这样图片的一部分就被隐藏起来了。

按钮置于最上层

由于 canvas 是优先级最高的,总是会覆盖页面上的其他内容,所以「保存图片」的按钮可能会被覆盖掉而显示不出来,可以通过在 button 上套一层 cover-view 来解决。

总结

图片绘制本来应该是一个非常简单也非常成熟的技术,其他的框架都会有对应的组件来处理这些事情,可是微信小程序的 canvas 绘制可以用「非常难用」来形容,希望微信团队能尽快优化。

你可以点击「阅读原文」获取源码。

更多原创文章我会第一时间发布在公众号:wang_little_yong ,欢迎关注

微信小程序 canvas 绘图问题总结的更多相关文章

  1. 微信小程序 | canvas绘图

    1.新的尺寸单位 rpx rpx(responsive pixel): 可以根据屏幕宽度进行自适应. 规定屏幕宽为750rpx.如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则 ...

  2. uniapp微信小程序canvas绘图插入网络图片不显示

    网络图片缓存 在uni中wx可以用uni代替 无区别: 先把要插入的网络图片缓存(getImageInfo); let context = uni.createCanvasContext('first ...

  3. 原创:WeZRender:微信小程序Canvas增强组件

    WeZRender是一个微信小程序Canvas增强组件,基于HTML5 Canvas类库ZRender. 使用 WXML: <canvas style="width: 375px; h ...

  4. 微信小程序 canvas 字体自动换行(支持换行符)

    微信小程序 canvas 自动适配 自动换行,保存图片分享到朋友圈  https://github.com/richard1015/News 微信IDE演示代码https://developers.w ...

  5. 微信小程序-canvas绘制文字实现自动换行

    在使用微信小程序canvas绘制文字时,时常会遇到这样的问题:因为canvasContext.fillText参数为 我们只能设置文本的最大宽度,这就产生一定的了问题.如果我们绘制的文本长度不确定或者 ...

  6. 微信小程序--canvas画布实现图片的编辑

    技术:微信小程序   概述 上传图片,编辑图片大小,添加文字,改变文字颜色等 详细 代码下载:http://www.demodashi.com/demo/14789.html 概述 微信小程序--ca ...

  7. 微信小程序canvas生成并保存图片

    ---恢复内容开始--- 微信小程序canvas生成并保存图片,具体实现效果如下图     实现效果需要做以下几步工作 一.先获取用户屏幕大小,然后才能根据屏幕大小来定义canvas的大小 二.获取图 ...

  8. 技术博客--微信小程序canvas实现图片编辑

    技术博客--微信小程序canvas实现图片编辑 我们的这个小程序不仅仅是想给用户提供一个保存和查找的平台,还希望能给用户一个展示自己创意的舞台,因此我们实现了图片的编辑部分.我们对对图片的编辑集成了很 ...

  9. 微信 小程序 canvas

    测试手机为IPHONE6,开发者工具版本0.10.102800.开发者工具0.11.112301版本也一样 微信小程序里的canvas 非 h5 canvas有很多不一样的地方,以下把微信小程序的ca ...

随机推荐

  1. 【js基础】创建对象的几种常见模式(工厂模式,构造函数模式,原型模式,构造原型组合模式)

    一.工厂模式 缺点:没有解决对象识别的问题 优点:解决了创建多个相似对象的问题 function createPerson(name,age,job){ var o = new Object(); o ...

  2. Python不可变对象

    str是不变对象,而list是可变对象. 对于不可变对象,比如对str进行操作: # 对于list进行操作,list内部的内容是会变化的: >>> a = ['c', 'b', 'a ...

  3. Python多继承

    # -*- coding: utf-8 -*- """ Created on Tue Nov 13 16:56:03 2018 @author: zhen "& ...

  4. 【PAT】B1065 单身狗(25 分)

    #include<stdio.h> #include<algorithm> #include<math.h> using namespace std; int ca ...

  5. Linux之删除带有空格的文件(而不是目录)

    大家平时工作中对不带空格的文件接触较多.这样一来删除操作也是比较简单的.但是有时我们会接触带有空格的文件.对于这种文件我们应该如何删除呢? 首先我们演示一下find命令结合xargs命令删除不带空格的 ...

  6. 17秋 软件工程 团队第五次作业 Alpha Scrum1

    题目:团队作业--Alpha冲刺 17秋 软件工程 团队第五次作业 Alpha Scrum1 各个成员在 Alpha 阶段认领的任务 伟航:督促和监督团队进度,协调组内合作 港晨:APP前端页面编写: ...

  7. select for update引发死锁分析

    本文针对MySQL InnoDB中在Repeatable Read的隔离级别下使用select for update可能引发的死锁问题进行分析. 1. 业务案例 业务中需要对各种类型的实体进行编号,例 ...

  8. POJ1419 Graph Coloring

    嘟嘟嘟 求无向图的最大独立集. 有这么一回事:最大独立集=补图的最大团. 所谓的最大团,就是一个子图,满足图中任意两点都有边. 然后ssy巨佬告诉了我一个很没有道理强的做法:随机. 每一次random ...

  9. HTML5的快速使用和css3的入门知识汇总

    各位开发者朋友和技术大神大家好!博主刚开始学习html5 ,自本周开始会每周更新技术博客,与大家分享每周所学.鉴于博主水品有限,如发现有问题的地方欢迎大家指正,有更好的意见和建议可在评论下方发表,我会 ...

  10. 转载 使用axis2构建webservice

    axis2是可以实现webservice的一个插件,使用这个插件可以发布webservice 1:可以使用这个插件来发布webservice,可以看网址:http://clq9761.iteye.co ...