node 文字生成图片

4,632 阅读4分钟

背景

不知不觉,公众号【前端名狮】已经做了三个月时间了,期间共更新了22篇解析经典面试题的文章,60篇精选文章,真的是困苦和收获共存的三个月。

公众号发布文章时,需要为文章配置一个封面图片。我的常规做法就是网上搜一张图片,然后利用 PhotoShop,在图片上加入文章标题,然后导出生成图片,如下图所示:

上图实际就是在一张背景图中,加入了一行文字。操作步骤简单,但是每次都需要打开PhotoShop修改文字,感觉麻烦、工作重复。

能不能用代码,解决日常生活中遇到的重复性工作呢?

实现方案

整体思路:

文字和图形不能直接合并,需要将文字先转换成图形,然后再将图形进行合并,大致步骤如下:

  1. 利用text-to-svg,将文字转成SVG图形;
  2. 利用sharp,将SVG图形与背景图片合并;

分析实现:

1. 将文字转为SVG图形

将文字转换为SVG图形,需要借助Node的模块text-to-png,该模块能够将文字按照指定字体生成SVG图形。

SVG 意为可缩放矢量图形(Scalable Vector Graphics),放缩时不损失图形质量,SVG 是使用 XML 格式定义的图像,如下所示:

在html页面中嵌入了一个SVG表示三角形

<!DOCTYPE html>
<html>
<body>

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
  <path d="M150 0 L75 200 L225 200 Z" />
</svg>

</body>
</html>

展示效果:

SVG很好的充当了中间变量的角色,言归正传,看下代码如何实现转换:

let path = require('path');
let TextToSVG = require('text-to-svg');

// 字体可以下载也可以从C:\Windows\Fonts复制
let fontPath = path.join(__dirname, './fonts/msyhbd.ttf');
let textToSVG = TextToSVG.loadSync(fontPath); // 加载字体文件

let options = {
    x: 0,         //文本开头的水平位置(默认值:0)
    y: 0,         // 文本的基线的垂直位置(默认值:0)
    fontSize: 36, // 字体大小
    anchor: 'top', // 坐标中的对象锚点
    // letterSpacing: "",  // 设置字母的间距
    attributes: {
        fill: '#FFFFFF' // 文字颜色
    }
}
let textSVG = textToSVG.getSVG('【前端名狮】', options);
console.log(textSVG);

输出结果:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="72" height="47.513671875"><path fill="#FFFFFF"
d="M23.94 7.95L23.94 7.95L29.67 9.39Q28.65 10.65 27.54 11.92L27.54 11.92L35.40 11.92L35.40 16.07L0.56 16.07L0.56 11.92L8.03 11.92Q7.24 10.63 6.40 9.39L6.40 9.39L11.67 7.95Q13.03 9.98 14.22 11.92L14.22 11.92L21.36 11.92Q22.71 9.95 23.94 7.95ZM28.72 35.51L28.72 17.58L33.47 17.58L33.47 37.02Q33.47 39.39 32.43 40.71Q31.39 42.03 29.53 42.28Q27.67 42.54 22.85 42.54L22.85 42.54Q22.54 40.50 21.83 37.58L21.83 37.58Q25.03 37.72 26.68 37.72L26.68 37.72Q28.72 37.72 28.72 35.51L28.72 35.51ZM7.35 34.95L7.35 42.50L2.57 42.50L2.57 18L19.27 18L19.27 37.51Q19.27 39.80 18.21 41.01Q17.16 42.22 15.22 42.37Q13.29 42.52 10.58 42.54L10.58 42.54Q10.02 39.52 9.60 37.86L9.60 37.86Q12.27 38.00 12.76 38.00L12.76 38.00Q14.48 38.00 14.48 36.07L14.48 36.07L14.48 34.95L7.35 34.95ZM14.48 24.82L14.48 22.29L7.35 22.29L7.35 24.82L14.48 24.82ZM7.35 28.62L7.35 31.15L14.48 31.15L14.48 28.62L7.35 28.62ZM21.76 35.33L21.76 18.60L26.16 18.60L26.16 35.33L21.76 35.33ZM69.33 18.18L50.13 18.18L50.13 10.16L54.21 10.16L54.21 14.10L57.45 14.10L57.45 7.95L61.98 7.95L61.98 14.10L65.25 14.10L65.25 10.16L69.33 10.16L69.33 18.18ZM36.88 18.67L36.88 14.24L41.12 14.24Q39.96 11.44 39.02 9.63L39.02 9.63L43.17 7.98Q44.12 9.70 45.74 12.94L45.74 12.94L42.52 14.24L48.52 14.24L48.52 18.67L36.88 18.67ZM44.09 19.41L44.09 19.41L48.34 19.93L45.93 34.00L48.34 33.57Q48.20 34.70 48.02 38.00L48.02 38.00Q43.10 38.85 37.27 40.11L37.27 40.11L36.49 35.51L42.28 34.59Q43.28 27.35 44.09 19.41ZM36.91 20.18L40.71 19.55L42.54 32.27L38.64 32.94Q37.93 26.40 36.91 20.18L36.91 20.18ZM48.87 24.33L48.87 20.18L70.73 20.18L70.73 24.33L61.24 24.33L60.68 26.54L70.24 26.54L70.24 39.90Q70.24 41.75 69.06 42.29Q67.89 42.84 66.29 42.84L66.29 42.84Q65.13 42.84 63.95 42.64L63.95 42.64L63.72 40.89L60.64 40.89L60.64 30.69L58.64 30.69L58.64 40.89L55.20
40.89L55.20 30.69L53.19 30.69L53.19 42.64L49.04 42.64L49.04 26.54L56.30 26.54L56.76 24.33L48.87 24.33ZM66.09 37.97L66.09 30.69L64.09 30.69L64.09 38.74Q65.07 38.85 65.34 38.85L65.34 38.85Q66.13 38.85 66.09 37.97L66.09 37.97Z"/></svg>

2. 合并图形

用于合并图片的库有很多,比如gm、jimp、mapnik、sharp等,其中sharp是基于libvips库来实现的,性能是最高的,所以我采用了sharp来合并图形。

let textSVG = Buffer.from(textSVG);
let bgPath = path.join(__dirname, './img/bg.jpg');
let targetPath = path.join(__dirname, '../dist/bg.jpg');
sharp(bgPath).composite([{
        input: textSVG,
        gravity: 'center'
    }]).toFile(targetPath);

sharp库注意事项

  1. 因为libvips是基于c++实现的,所以sharp库需要基于C++源代码进行编译构建后才能使用。node-gyp是为node编译C++扩展的时候使用的编译工具,但是node-gyp依赖pythonVC++构建工具来进行编译。所以需要先安装python 和 VC++ 环境。最简单的方式就是顺序执行下面安装命令:
// 安装构建环境python、vc++
npm install --global --production windows-build-tools

// 安装node-gyp 编译工具
npm install --global node-gyp

// 安装sharp
npm install sharp
  1. 官方文档中,用sharp合并图像时,给出的api是 overlayWith,但是你会发现,这个api并不存在。这个是因为sharp最新版本0.23.3删除了overlayWith,用composite进行了替换。

至此,我们就实现了一个简单的生成公众号封面图片的功能,让我们看看生成效果:

总结

程序可以帮助我们干重复的事情,提高我们的生产力,如果程序猿写的代码都用于解决自己生活中遇到的问题,对程序猿无疑是巨大的动力源泉。

推荐阅读

  1. 【第22题】理解 JS 模块化
  2. 【深入vue】为什么Vue3.0不再使用defineProperty实现数据监听?
  3. 抛弃jenkins,如何用node从零搭建自动化部署管理平台
  4. 前端部署演化史
  5. 深入理解 ES6 Iterator
  6. 解读HTTP/2与HTTP/3 的新特性(推荐)

关注我

扫一扫 关注我的公众号【前端名狮】,更多精彩内容陪伴你!