需求

公司开发微信小程序,有一个海报页面,需要用户点击生成海报,可以将该该swipe-item 生成一个带二维码的图片,最终由纯前端实现!

技术调研

  • 因为小程序的打包限制,不可能将所有的图片都放在代码目录里面。所以就得使用远端的图片,但是因为canvas对跨域图片的不支持,可以使用微信小程序中的API :wx.getImageInfo()现将远端的图片临时保存。
  • canvas 组件是由客户端创建的原生组件,它的层级是最高的,不能通过 z-index 控制层级;并且使用display:none 和 visibility:hidden 的方式隐藏会导致canvas无法捕获画布内容,所以通过给canvas外部嵌套一个width:0;height:0;overflow:hidden的父级。

实现步骤

将远端图片暂存本地(以用户头像为例)

wx.getUserInfo({    //获取微信用户信息success: function (res) {this.getImageInfo(res.userInfo.avatarUrl);  //  调取图片处理方法this.setData({userName: res.userInfo.nickName});}});
getImageInfo(url){    //  图片缓存本地的方法if(typeof url === 'string'){wx.getImageInfo({   //  小程序获取图片信息APIsrc: url,success: function (res) {this.setData({head_img:res.path})},fail(err) {console.log(err)}})}

canvas绘制图片

点击生成海报按钮

handlePoster(e){wx.getSetting({  // 获取用户设置success(res) {if (!res.authSetting['scope.writePhotosAlbum']) {  // 如果用户之前拒绝了授权wx.openSetting({success(tag){if (tag.authSetting["scope.writePhotosAlbum"]){  // 用户在设置页选择同意授权// wx.showLoading({//   title: '正在生成...',// })}}});}else{   //  用户已经授权wx.showLoading({title: '正在生成...',})}}})

此时页面出现loading状态,canvas开始绘制海报:

首先绘制整个底部背景

在这里,我暂且用本地图片作为演示代替。绘制的canvas图片大小为750px*1344px大小,最终生成格式为jpg。大小大概就200多kb。非常的小,清晰度也不错。

我选择的背景图如上图所示;

    const ctx = wx.createCanvasContext('notes');ctx.clearRect(0, 0, 0, 0); const arr2 = ['./big_img1.png', this.data.nodesData[index].detail_pic];    // 有图片海报背景图&&海报正文图片const WIDTH=750;const HEIGHT=1334;//  绘制图片模板的 底图ctx.drawImage(arr2[0], 0, 0, WIDTH, HEIGHT);
绘制海报的正文图片
//  绘制图片模板的 banner图ctx.drawImage(arr2[1], 40,40, 670, 580);
绘制时间

因为我们的海报上面的时间 xxxx.xx.xx中的每个数字和点都是图片,所以时间也是一个个的小的以数字命名的图片绘制上去。而后台提供给我们的时间是个 秒(s)为单位的时间戳。首先得将时间戳转换为一个时间数字组成的数组:

dateFilter(date){let gmt = new Date(date * 1000);let nYear=String(gmt.getFullYear());let nMonth =this.numFormatting(gmt.getMonth()+1);let nDay =this.numFormatting(gmt.getDate());let end_date = (nYear + '.' + nMonth + '.' + nDay).split("") ;return end_date},/***  处理 月份 天数 个位数*/numFormatting(num){if(String(num).length<2){return '0'+num}else{return num}},

假设处理好的时间格式为 :

let times=['2', '0', '1', '8', '.', '0', '4','.','1','2'];

接下来是绘制时间:

 //  绘制 图片模板 的时间const TEXT_DATE = ['2', '0', '1', '8', '.', '0', '4','.','1','2'];for (let i = 0; i < TEXT_DATE.length; i++) {if (TEXT_DATE[i] != '.') {var path3 = `./${TEXT_DATE[i]}.png`;} else {var path3 = './point.png';}let clientx = 40 + 16 * i;ctx.drawImage(path3, clientx, 640, 16, 32);}
绘制用户头像

因为二维码中显示的用户头像是一个圆形图像,所以处理方式为:

// 绘制头像ctx.save();let r=32;let d = r*2;let cx = 102;let cy = 1172;ctx.arc(cx+r, cy+r, r, 0, 2 * Math.PI);ctx.clip();ctx.drawImage(this.data.head_img, cx, cy, d, d);ctx.restore();

这个时候 ,海报所需要的所有图片已经绘制成功,接下来我们开始处理文字部分:

canvas 绘制文字

canvas并不会自动的将文字折行处理,所以我们得自己考虑每行显示多少个文字,还得考虑中英文和符号所占字节的不同,在此,封装一个处理方法:

textByteLength(text,num){  // text为传入的文本  num为单行显示的字节长度let strLength = 0; // text byte lengthlet rows=1;let str=0;let arr=[];for (let j = 0; j < text.length; j++) {if (text.charCodeAt(j) > 255) {strLength += 2;if (strLength > rows * num) {strLength++;arr.push(text.slice(str, j));str = j;rows++;}} else {strLength++;if (strLength > rows * num) {arr.push(text.slice(str, j));str = j;rows++;}}}arr.push(text.slice(str, text.length));return [strLength, arr, rows]   //  [处理文字的总字节长度,每行显示内容的数组,行数]},

这个时候 就可以开始绘制文字了:

绘制正文和 出处
const CONTENT_ROW_LENGTH = 40;  // 正文 单行显示字符长度let [contentLeng, contentArray, contentRows] = this.textByteLength(this.data.nodesData[index].text, CONTENT_ROW_LENGTH);ctx.setTextAlign('left')ctx.setFontSize(32);let contentHh = 32 * 1.3;for (let m = 0; m < contentArray.length; m++) {ctx.fillText(contentArray[m], 40, 732 + contentHh * m);}//  绘制 出处ctx.setTextAlign('right')ctx.setFontSize(32);ctx.fillText(`——${this.data.nodesData[index].refer}`, 710, 996, 710);
绘制二维码边上的说明
//  绘制二维码右边说明ctx.setTextAlign('left')ctx.setFontSize(28);ctx.setFillStyle('rgba(34,34,34,.64)')ctx.fillText('长按小程序码', 250, 1174);ctx.fillText(`${this.data.userName}邀你进入掌阅读好书`, 250, 1230);ctx.draw();

此时如果canvas标签能够显示查看,就能看到一个完美的海报绘制完成,现在只差最后一步,保存canvas;使用微信方法 canvasToTempFilePath()将canvas海报保存到本地临时文件路径;在使用saveImageToPhotosAlbum()将图片保存到本地相册:

setTimeout(function () {wx.canvasToTempFilePath({canvasId: 'notes',fileType:'jpg',success: function (res) {wx.saveImageToPhotosAlbum({filePath: res.tempFilePath,success(res) {wx.hideLoading();wx.showToast({title: '保存成功',});},fail(){wx.hideLoading()}})}})}, 500);

然后查看存储图片的路径文件夹,最终生成的海报:

总结:

在做这个功能之前,canvas用的非常少,很多方法都是现成百度查询得出来的结果,这次的canvas生成海报并保存本地的实现过程中,让我学到了很多东西;因为项目做得比较急,很多的代码没有经过细致的打磨,在此,也希望看到本文章的朋友们及时指点。

微信小程序纯前端生成海报并保存本地相关推荐

  1. 微信小程序使用canvas绘制海报并保存本地相册

    在做微信小程序的时候,很多都会用到生成海报分享功能,刚好最近项目有这个需求,今天就发出来记录下 首先是使用canvas绘制一张海报,微信小程序的canvas有老版本和新版本我是用的是新版本 代码如下 ...

  2. uniapp实现微信小程序端动态生成海报

    背景: 基于uniapp实现微信小程序中商品详情的海报生成与保存 效果图: 思路: 首先把海报上需要的内容准备好,比如用户头像,商品信息,二维码等.需要注意的是,因为二维码是动态生成的,所以需要后端传 ...

  3. 微信小程序实现画布生成海报功能

    微信小程序可以通过使用 标签来实现生成海报的功能.以下是基本实现步骤: 1.在 WXML 文件中创建一个 标签,并设置其宽度和高度属性.' <canvas canvas-id="myC ...

  4. 记一次微信小程序canvas 2d 生成海报问题

    因项目需要,需要制作海报分享. 如: 事情总是不是那么顺利,canvas生成海报生成中遇到各种奇葩问题.一开始是 wx.canvasToTempFilePath 中获取不到canvas对象,调用返回  ...

  5. uniapp开发微信小程序使用painter生成海报

    最初绘制海报时是准备用canvas绘制,但是绘制遇到各种问题,且难度颇高,最后也没能绘制出来,也尝试过使用微信官方的 wxml-to-canvas,但需要传入wxml和样式,太为难我这个小小的后端开发 ...

  6. 在微信小程序中实现生成海报图并保存到相册

    效果图镇楼: 技术依赖: 弹窗 (vant-weapp 提供的 van-popup 组件) 海报图 (wx-canvas-2d 工具) 弹窗组件的使用方式可以点击上面链接查看,本篇主要讲解海报图绘制方 ...

  7. 微信小程序利用canvas生成海报-------图片为网络图片

    根据我们老总的业务需求,迫不得已,我做了这个canvas绘制的海报,感觉基本上可以解决现在海报所遇到的大部分问题了,献给那些没有做过的小伙伴们,话不多说,先上我做的效果 上代码 <style&g ...

  8. uniapp微信小程序开发,生成海报插件painter的使用

    1.引入painter插件 下载地址:https://github.com/Kujiale-Mobile/Painter 代码下载后,将component中的painter文件夹放入项目wxcompo ...

  9. 仿qq邮箱源码程序_QQ微信头像制图工具箱小程序纯前端源码

    今天在网上看到了一个微信小程序源码,经测试QQ小程序也可以完美运行,所以给大家分享一下这个QQ微信头像制图工具箱小程序纯前端源码. 主要功能有文字九格.头像挂件生成.爆趣九宫格.形状九宫格.创意长图. ...

最新文章

  1. ImportError: No module named tensorflow.compat.v1 忽略已经安装的某个包版本 忽略已安装版本...
  2. 剑指offer 算法(数组 字符串)
  3. Python机器学习笔记:深入理解Keras中序贯模型和函数模型
  4. 多个类的DLL封装及调用
  5. one_code=soup.find('a',href=re.compile(rill)) NameError: name 're' is not defined
  6. 解决margin-top塌陷问题的六种方法
  7. 表视图(UITableView)与表视图控制器(UITableViewController)
  8. 通过字节流来代替链接来下载小文件
  9. 【2019“新智认知”杯: C】CSL的密码(求长度≥k的不同子串数---后缀数组)
  10. 运行在一个完全隔离环境中的完整计算机系统,凤凰系统完全释放PC性能 模拟器是指通过软件模拟具有完整硬件系统功能、运行在一个完全隔离环境中的计算机系统...
  11. 如何使用cmd查看jdk版本
  12. 增强安全性、支持跨页逻辑关系设定的电信运营级EnableQ在线问卷调查引擎V1.60来了......
  13. w10电脑文件不能放到服务器,w10设置文件服务器
  14. 电子科技大学信通2018级学生上早自习缺勤率情况分析
  15. CentOS-7安装Cinnamon Desktop
  16. 抽象类 [Java]
  17. 验证CUDA和CUDNN是否安装成功的方法
  18. php kafka使用
  19. 轻松省力清洁地面,分分钟搞定家务,云米智能洗地机Cyber Lite体验
  20. g711原理pcm转alaw,pcm转ulaw,alaw转pcm,ulaw转pcm

热门文章

  1. 一个链接泄露这么多隐私,你还敢拼多多助力吗?
  2. 基桩静荷载测试数据分析软件,静荷载基桩检测原理及应用技术
  3. 2015年7月深圳社保缴费基数费率表
  4. 微信小程序腾讯服务器地址要购买吗,微信小程序JavaScript SDK
  5. 码码在线考勤系统笔记(三)
  6. 定制海报、AI扣人像小程序
  7. 双目九视清哺光仪_岳清江|坚定信念,普通人也能拥有非凡人生——【管鹏企业家书友会】...
  8. ffmpeg m3u8 与 mp4 相互转换
  9. 台式计算机如何安装摄像头,台式机如何使用摄像头
  10. js前置递增和后置递增