type
status
date
slug
summary
tags
category
icon
password
功能描述:
- 需要前端绘制图片+文字导出;
- 文字可编辑,字体只有ttf;
- 可以导出图片存储到oss;
简版需求:
- 先不考虑字体,实现起来很简单,load图片绘制到canvas中,回调中把文字绘制进去;
- 文字是可以编辑的: clearRect => drawImg => drawText;
- 这里可以稍微优化一下:
- image和text分别作为一层,因此不必等待图片加载就可以先绘制文字图层,重绘文字的时候只需要重绘文字部分就行;
- 需要导出的时候调canvas的toDataURL导出BASE64数据就行;
- 考虑到数据传输成本,不应该在前端导出图片,所以最终方案是:
- 前端做一次绘制用于预览效果,配置文件同步发送给后台进行服务端生成并存储oss,之后返回给前端的只是一个url;
完整功能
- 由于字体只有ttf,本来考虑的是每输入一批文字就去批量生成对应的woff字体文件;
- 但是由于会产生过多的临时字体,所以继续用服务端导出图片这个服务,那就需要再加一下字体功能:
- 合成图片的服务使用node-canvas来实现;
- 这个库是可以调用本地的ttf字体来渲染文字的,所以上边的问题就很好解决;
- 现在的流程是:
- 使用文字配置信息调用文字转图片的服务,生成字体图片;
- 前端拿到后绘制到文字图层,此时的文字图层其实又是一个image图层;
流程设计
- 生成完整图文信息
- 获取配置文件,根据配置文件中的文字信息预加载字体文件,保存到本地;
- 从网络获取图片,转base64后再开始绘制
- 用base64数据绘制背景,本地读取字体绘制文字,导出图片
- 生成文字图片服务
- 从网络字体获取下载到本地,之后调用文字绘制服务来生成base64数据
- 优化
- 下载的字体文件要包含任意文字,所以体积会很大,使用字体名称来做标志
- 下载前匹配参数中的字体名称和本地文件,如果对应则不再下载,忽略字体名欺骗行为
- 如果发生字体名称欺骗,则会导致所以对应字体都无法正常使用,加一个删除指定字体的接口
问题记录
实际做起来总会碰到问题,尤其是不熟悉的情况下(有些问题很小白)
- 文字是一个string数组,有多个文字要转换,如何保证字体以及图片全部下载完成?
- 使用Promise.all 并行下载图片,全部返回(部分失败未处理)后进行下一步
- 怎么下载图片(小白问题)
- 开始使用request,有点麻烦,github搜了下,发现了base64-img,虽然star少,不过对新手来说的确方便,一行代码:
- 绘制文字图片有没有遇到问题
- 这个真的有,canvas绘制文字是有偏移量的
- stackoverflow找了几个发现偏移量还是计算出错
- 自己用PS测试了各种字号绘制出来的图片,暂时没有找到通用的偏移量和比例
- 自己研究字体渲染显然费事费力,没有那么多时间在一个问题上卡太久
- 最终搜到了这个库node-canvas-text
- 还遇到什么问题了?
- 有个库需要使用了ES6 export default,require获取不到,临时改下导出方式,线上总不能改;
- 直接把代码都改了ES6(渣渣水平),然后又出现了更多的问题....
- 本地测试一切完美,但是服务器总要在linux上吧,于是vagrant上进行测试,发现死活跑不起来;
- 警告如下:
- fs: re-evaluating native module sources is not supported.
- if you are using the graceful-fs module, please update it to a more recent version.
- 研究了好久发现根本和这个没关系,Y的就是不支持linux
- 看后边的报错, not find Promise module,明明是引用了的 !!!!
- !!? 突然想起来,ES6本身就有这家伙,我的命名还和它重复了,都叫 Promise
- 删掉以后果然ok了!!!
ps
- 遇到需要的功能别忘了Google和github,有质量好的的就不要总想着自己搞定,专注于自己要做的时期;
- 遇到问题欢迎stackoverflow,这个网站质量不错;