侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

微信小程序利用Canvas绘制图片和竖排文字详解

微信(小程序)  /  管理员 发布于 5年前   522

前言

闲暇时间抽个空写了个三国杀武将手册的小程序,中间有个需求设计的是合成武将皮肤图、竖排的武将姓名、以及小程序码,然后提供保存图片到相册,最终让用户可以分享到朋友圈或其他平台。合成图片应该按照 Canvas 的文档来做都没什么问题,主要是有个竖排文字的需求,这里和大家分享一下。

正文

首先放一张最终保存到相册的图片吧~

自我感觉良好,至少达到了我自己的预期吧~~~

下面让我们一步一步来看看如何实现的吧。

整个图片分为三个部分:

  • 武将图片
  • 小程序码
  • 武将文字信息

先来看一下 wxml 里面的代码,主要是放了一个 canvas 标签,控制了一下高度和宽度属性。

武将图片

drawHeroImage: function (path) {var that = this;// 拿到canvas contextlet ctx = wx.createCanvasContext('share_canvas');// 为了保证图片比例以及绘制的位置,先要拿到图片的大小wx.getImageInfo({src: path,success: function (res) {// 计算图片占比信息 let maxWidth = Math.min(res.width, that.data.canvasWidth * 0.65);let radio = maxWidth / res.width;let offsetY = (that.data.canvasHeight - res.height * radio) / 2;console.log('offsetY=' + offsetY);that.setData({imageWidth: res.width * radio,imageHeight: res.height * radio,offsetY: offsetY,});// 绘制canvas背景,不属于绘制图片部分ctx.setFillStyle('white')ctx.fillRect(0, 0, that.data.canvasWidth, that.data.canvasHeight);// 绘制武将图片,path是本地路径,不可以传网络url,如果是网络图片需要先下载ctx.drawImage(path, 10, offsetY, res.width * radio, res.height * radio)// 绘制小程序码that.drawQrCodeImage(ctx);// 绘制势力汉字:吴that.drawInfluence(ctx, that.data.hero.HERO.INFLUENCE);// 绘制武将姓名:陆逊that.drawName(ctx, that.data.hero.HERO.NAME);// 绘制武将称号:江陵侯that.drawHorner(ctx, that.data.hero.HERO.HORNER);// 最终调用draw函数,生成预览图// 一个坑点:只能调用一次,否则后面的会覆盖前面的ctx.draw();}});}

小程序码

小程序码和武将图片是一个类型,无非就是需要计算绘制的位置,这里就不再展示相关代码了。

武将文字信息

从刚刚的代码可以看出,我分了3个部分来绘制,其实 吴 和 陆逊 应该是可以放到一起的,但是我在绘制的时候发现,空格在绘制的时候会引起异常,导致空格后面的文字无法绘制出来,所以我这里 吴 和 陆逊 中间的空白是靠位置偏移来做的。

这里就展示一下如何绘制武将称号的。

// 绘制武将称号:江陵侯drawHorner: function (ctx, text) {// 设置字号ctx.setFontSize(26);// 设置字体颜色ctx.setFillStyle("#000000");// 计算绘制起点let x = this.data.offsetX + 35;let y = this.data.offsetY + 10;console.log('drawHorner' + text);console.log(x);console.log(y);// 绘制竖排文字,这里是个Util函数,具体实现请继续看Canvas.drawTextVertical(ctx, text, x, y);}

绘制竖排文字从网上找了个开源的代码,需要看原理的请看这里

当然我这里为了适用小程序做了些改动,函数原型是这样子的:

CanvasRenderingContext2D.prototype.letterSpacingText = function (text, x, y, letterSpacing)

原谅我不是很会 js ,完全不懂这是个什么语法,看了一会没弄懂,感觉像是给类添加新的属性,不管他。

不管白猫黑猫,能抓到耗子就是好猫

改造后的函数像下面的样子:

canvas.js /*** @author zhangxinxu(.com)* @licence MIT* @description http://www.zhangxinxu.com/wordpress/?p=7362*/function drawTextVertical(context, text, x, y) {var arrText = text.split('');var arrWidth = arrText.map(function (letter) {return 26;// 这里为了找到那个空格的 bug 做了许多努力,不过似乎是白费力了// const metrics = context.measureText(letter);// console.log(metrics);// const width = metrics.width;// return width;});var align = context.textAlign;var baseline = context.textBaseline;if (align == 'left') {x = x + Math.max.apply(null, arrWidth) / 2;} else if (align == 'right') {x = x - Math.max.apply(null, arrWidth) / 2;}if (baseline == 'bottom' || baseline == 'alphabetic' || baseline == 'ideographic') {y = y - arrWidth[0] / 2;} else if (baseline == 'top' || baseline == 'hanging') {y = y + arrWidth[0] / 2;}context.textAlign = 'center';context.textBaseline = 'middle';// 开始逐字绘制arrText.forEach(function (letter, index) {// 确定下一个字符的纵坐标位置var letterWidth = arrWidth[index];// 是否需要旋转判断var code = letter.charCodeAt(0);if (code <= 256) {context.translate(x, y);// 英文字符,旋转90°context.rotate(90 * Math.PI / 180);context.translate(-x, -y);} else if (index > 0 && text.charCodeAt(index - 1) < 256) {// y修正y = y + arrWidth[index - 1] / 2;}context.fillText(letter, x, y);// 旋转坐标系还原成初始态context.setTransform(1, 0, 0, 1, 0, 0);// 确定下一个字符的纵坐标位置var letterWidth = arrWidth[index];y = y + letterWidth;});// 水平垂直对齐方式还原context.textAlign = align;context.textBaseline = baseline;}module.exports = {drawTextVertical: drawTextVertical}

绘制网络图片

由于网络图片无法直接绘制,所以需要先下载到本地,然后再按住本地图片绘制的流程走一遍。

downloadHeroImage: function () {// 微信不支持非https的图片下载,这里了个替换let url = this.data.hero.HERO.ICON.replace(/http/, "https");var that = this;wx.downloadFile({url: url,success: function (res) {// 下载成功后拿到图片的路径,然后开始绘制var path = res.tempFilePath;that.drawHeroImage(path);}, fail: function (res) {console.log(res)}});}

保存图片

说了这么多,自然少不了最终的一步,将绘制到 canvas 的图片保存到手机相册,这里需要用户授权,你需要自己处理。
用的是微信给我们提供的接口 wx.canvasToTempFilePath 。需要我们传入起点坐标 (x, y)和画布大小 (width, height) 以及 canvasId 。

saveShareImage: function () {wx.showLoading({title: '正在保存图片..',});let that = this;wx.canvasToTempFilePath({x: 0,y: 0,width: that.data.canvasWidth,height: that.data.canvasHeight,canvasId: 'share_canvas',success: function (res) {wx.saveImageToPhotosAlbum({filePath: res.tempFilePath,success(res) {console.log(res);wx.showToast({title: '保存到相册成功',duration: 1500,})},fail(res) {console.log(res)wx.showToast({title: '保存到相册失败',icon: 'fail'})},complete(res) {console.log(res)}})}})}

开源

本着开源的精神,源码已经放在 Github 上,大家可以去上面查看具体代码。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

您可能感兴趣的文章:

  • 微信小程序简单的canvas裁剪图片功能详解
  • 微信小程序如何调用图片接口API并居中显示
  • 关于微信小程序获取小程序码并接受buffer流保存为图片的方法
  • 微信小程序上传图片到php服务器的方法
  • 详解微信小程序文件下载--视频和图片
  • 微信小程序实现富文本图片宽度自适应的方法
  • 微信小程序图片左右摆动效果详解


  • 上一条:
    微信小程序Echarts图表组件使用方法详解
    下一条:
    微信小程序数据统计和错误统计的实现方法
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 微信模板消息改版后发送规则记录(微信订阅消息参数值内容限制说明)(1个评论)
    • 微信支付v3对接所需工具及命令(0个评论)
    • 2023年9月1日起:微信小程序必须备案才能上线运营(0个评论)
    • 腾讯官方客服回应了:微信好友上限约10000个!(1个评论)
    • 2023年做微信小程序的老铁注意:新增收费项、微信小程序获取手机号也收费了(2个评论)
    • 近期文章
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2017-10
    • 2018-01
    • 2020-03
    • 2021-06
    • 2021-10
    • 2022-03
    • 2023-02
    • 2023-06
    • 2023-07
    • 2023-08
    • 2023-10
    • 2023-11
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客