Node.js 小打小闹之图片合成

栏目: Node.js · 发布时间: 5年前

内容简介:前阵子公司的产品经理找我谈个需求,希望能为每个用户生成专属的资讯分享图片及让开通专栏的用户能够生成专属的文章分享图片。这两天刚好有空,就抽空预研了 “生成专属的资讯分享图片” 这个功能。进入正题前,我们先来看一下最终实现的效果图:

前阵子公司的产品经理找我谈个需求,希望能为每个用户生成专属的资讯分享图片及让开通专栏的用户能够生成专属的文章分享图片。这两天刚好有空,就抽空预研了 “生成专属的资讯分享图片” 这个功能。

进入正题前,我们先来看一下最终实现的效果图:

Node.js 小打小闹之图片合成

需求分析

接下来我们来简单的介绍一下 “生成专属的资讯分享图片” 这个功能需求:

  1. 图片中有个区域能够显示分享用户的头像和昵称;
  2. 图片中需要显示用户的一些数据信息;
  3. 图片底部需要展示 App 的二维码信息。

针对这个需求,我们主要有两种方案:客户端生成与服务端生成。既然文章标题已定,我们肯定选择 “服务端生成” 的方案。确定完方案后,我并没有马上动手开始开发,而是先在网上找一些相关的文章,因为觉得这个需求应该挺常见的。果然通过一番检索,找到了 用程序生成一张在简书的专属分享图片 这篇文章。文章作者对功能做了详细的分析,然后利用 Python 强大的图片处理库 Pillow 进行功能实现。建议有兴趣的同学,直接阅读原文。

虽然 Python 勉强入门,作者写的代码也基本能看懂,但作为一个喜欢折腾的小前端,怎能不使用我们的 Node.js 来折腾一下呢?说做就做,马上到 npm 上挑选 Node.js 的图片处理库。经过一番筛选,最终选中了 sharp ,这是为什么?当然是喜欢它的名字咯(嘿嘿,其实是看中它的高性能)。

High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP and TIFF images. Uses the libvips library. http://sharp.pixelplumbing.com/

再次感谢 用程序生成一张在简书的专属分享图片 该文章的作者,他把项目源码和资源都放到了 Github - jianshu_share 上。因为只是技术预研,我就直接使用该项目的图片资源,接下来我们来介绍一下具体实现。

实现步骤

  • 裁剪头像(方形 -> 圆形):通过查看 sharp 项目的说明文档,我发现了裁剪头像的方案,具体实现如下:
// 创建圆形SVG,用于实现头像裁剪
const roundedCorners = new Buffer(
  '<svg><circle r="90" cx="90" cy="90"/></svg>'
);

/**
 * 生成圆形的头像
 * @param {*} avatarPath 头像路径
 */
function genCircleAvatar(avatarPath) {
  return sharp(avatarPath)
    .resize(180, 180)
    .overlayWith(roundedCorners, { cutout: true })
    .png()
    .toBuffer({
      resolveWithObject: true
    });
}
  • 叠加背景图、头像和二维码图层:这个功能与 PS 的图层叠加类似,其实就是把裁剪过的头像和二维码,贴到背景图的指定位置。要实现这个功能也是需要使用 sharp 提供的 overlayWith 方法。
// 组合多个图层:图片+文字图层
  return buffers
    .reduce((input, overlay, index) => {
      return input.then(result => {
        console.dir(overlay.info);
        return sharp(result.data)
          .overlayWith(overlay.data, overlayOptions[index])
          .toBuffer({ resolveWithObject: true });
      });
    }, backgroudBuffer)
    .then((data) => {
      return sharp(data.data).toFile(outFilePath);
    }).catch(error => {
      throw new Error('Generate Share Image Failed.');
    });
  • 根据用户信息创建文本:在实现这个功能的时候,遇到了一个问题。因为官方的 API 没有提供文件创建图片的方法,最终参考了 sharp 项目中 How to dynamically write text to image? 这个 issue 中提供的方案,解决了这个问题。 即利用 text-to-svg 这个库,先把文本转换成 SVG,然后在利用 overlayWith 方法进行图层合并。
// 加载字体文件
const textToSVG = TextToSVG.loadSync(path.join(__dirname, "./simhei.ttf"));

// 设置SVG文本元素相关参数
const attributes = { fill: "white" };
const svgOptions = {
  x: 0,
  y: 0,
  fontSize: 32,
  anchor: "top",
  attributes: attributes
};

/**
 * 使用文本生成SVG
 * @param {*} text 
 * @param {*} options 
 */
function textToSVGFn(text, options = svgOptions) {
  return textToSVG.getSVG(text, options);
}
  • 叠加所有图层,生成最终的图片:实现最后一步的时候,也是遇到了一个大坑,官方没有提供对应的方法。幸运的是,最终也是通过项目中 Easier way to composite 3+ layers 这个 issue 提供的方案,完美解决了问题。

经过大半天地折腾,终于借助 Node.js 的 sharp 这个图片处理库,基本实现了上述的功能。由于源码过长,我直接放在 Gist 上,有兴趣的小伙伴可以查看 gen-share-image.js 完整源码。

总结

本文主要介绍了如何利用 Node.js 的 sharp 图片处理库,生成专属的分享图片。源码中有很多细节需要处理,如动态获取头像、根据参数动态生成文本信息、异常处理及基于 Koa、Egg.js 或 Express 框架,创建对应的 API 服务等。 gen-share-image.js 只是介绍了完整的思路和实现方式,实际开发的时候,请根据具体需求进行调整。


以上所述就是小编给大家介绍的《Node.js 小打小闹之图片合成》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

程序员的数学2

程序员的数学2

平冈和幸、堀玄 / 陈筱烟 / 人民邮电出版社 / 2015-8-1 / CNY 79.00

本书沿袭《程序员的数学》平易近人的风格,用通俗的语言和具体的图表深入讲解程序员必须掌握的各类概率统计知识,例证丰富,讲解明晰,且提供了大量扩展内容,引导读者进一步深入学习。 本书涉及随机变量、贝叶斯公式、离散值和连续值的概率分布、协方差矩阵、多元正态分布、估计与检验理论、伪随机数以及概率论的各类应用,适合程序设计人员与数学爱好者阅读,也可作为高中或大学非数学专业学生的概率论入门读物。一起来看看 《程序员的数学2》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

随机密码生成器
随机密码生成器

多种字符组合密码

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具