需求:前后端分离的项目,由于后端数据用到了一些自造字,前端css引入了一些自造字字体,这样HTML页自造字就可以正常显示。
但是前端把自造字当作参数传到第三方系统时,第三方系统由于没有引入相关字体,会无法正常显示。第三方系统不是我们能控制的,所以想到把文字转成图片,把图片传给第三方系统,第三方系统直接显示图片。
想法:
1、API端实现图片生成,直接提供API URL给第三方系统。
需要在API引入字体,修改API端代码实现相关功能。第三方系统显示时要呼叫API,可能涉及跨域问题。
2、UI端实现图片生成,直接浏览器端脚本生成图片文件,保存在Local,提供图片路径给第三方系统。
通过脚本生成图片,但是无法自动保存到Local PC,好像只能实现自动下载,那就不是想要的效果了。
进一步想法:
由于生成的图片只是文字,不会太大,可以考虑把图片Base64传给第三方系统。
3、API端实现图片生成转为Base64,UI端通过API获取到Base64,再把Base64传给第三方。
需要在API引入字体,修改API端代码实现相关功能。
4、UI端JS脚本实现图片生成并转为Base64,再把Base64传给第三方。
简单直接,不需要额外的API。
弯路:
因为这些自造字JS从API取到是编码,但是HTML显示渲染后是正常的,所以就从HTML转图片的角度去查方案。查到了一些文章,觉得还挺适用。原理基本就是利用svg:
把需要转为图片的HTML内容利用svg的foreignObject标签包起来;
new一个Blog对象存储上面包好的svg;
用URL.createObjectURL为Blog对象生成URL;
把img的src指定为Blog对象的URL。
到这一步img已经生成好了,文章中还进一步提到,img载入完毕后,可以再利用canvas的drawImage把img重新画出来,然后通过canvas的toDataURL方法把画好的内容转为不同图片格式的Base64,比如png/jpg等。这也是为什么想到可以直接传Base64给第三方系统。
于是按照上面的步骤实作,实作过程中碰到过一些问题:
1、生成的img空白
svg如果使用foreignObject标签,需要指定所包HTML的xmlns为:http://www.w3.org/1999/xhtml,否则浏览器等不知道如何渲染。
svg如果使用text标签,需要设置x,y属性,否则好像默认是(0,0),导致内容显示到图片外面去了。
2、svg用foreignObject标签包HTML,最后一步使用canvas的toDataURL方法提示画布被污染执行失败(Tainted canvases may not be exported)
查了下好像说使用foreignObject标签就会有这个问题,没做具体测试验证,想说我们要生成的内容是纯文字,所以其实也不需要使用foreignObject标签包HTML,直接改用svg的text标签。
3、转出的Base64内容为空
要在img载入完毕才能调用canvas的drawImage方法,把dramImage写在img.onload里面。
4、生成的自造字图片没有正常显示
svg的text标签要再指定font-family。
最后:
终于实现了,但是突然发现绕了这么一大圈,我们其实只是需要把文字转成图片Base64,没有什么其它特别的HTML内容,是不是可以直接用canvas画文字,然后toDataURL。
于是最后,直接用canvas指定字体,调用fillText画出文字,然后toDataURL转为Base64。