Node.js终极文本转图指南

发布于:2025-08-30 ⋅ 阅读:(21) ⋅ 点赞:(0)

引言

简要介绍文字转图片的应用场景(如社交媒体分享、水印生成、动态海报等),以及Node.js在图像处理中的优势。提及ultimate-text-to-image库的核心功能和特点。

环境准备

所需工具和库的版本要求:

  • Node.js
  • npm或yarn包管理器
  • ultimate-text-to-image库的安装命令:
    npm install ultimate-text-to-image
    

UltimateTextToImage 基本用法

UltimateTextToImage 是一个用于将文本转换为图像的 Node.js 库,支持多种自定义选项如字体、颜色、对齐方式等。通过简单的配置,可以生成不同风格的文本图像。

将文本`abc xyz 0123456789 零一二三四五六七八九`转化为图片,图片宽度为200像素,字体为‘Sans,Arial’,首选‘Sans’,次选‘Arial’。将图片保存到项目的根目录下,图片名称为‘image1.png’

const { UltimateTextToImage } = require("ultimate-text-to-image");
const path = require("path");

new UltimateTextToImage(`abc xyz 0123456789 零一二三四五六七八九`, {
  width: 200,
  fontFamily: "Sans,Arial", //有些字体可能不支持中文
})
  .render()
  .toFile(path.join(__dirname, "image1.png"));

执行后的效果图:

高级配置选项

该库提供了丰富的配置参数,允许用户精细控制文本的显示效果。包括字体大小、颜色、背景、边框等属性,满足不同场景需求。

let textToImage = new UltimateTextToImage(
  "abc xyz 0123456789 零一二三四五六七八九",
  {
    width: 400,          // 初始画布宽度(px),若文本超出会自动调整
    maxWidth: 1000,      // 画布最大宽度(px),防止无限扩展
    maxHeight: 1000,     // 画布最大高度(px),超出可能截断
    fontFamily: "Sans",  // 字体(系统支持的字体,如 "Arial"、"SimSun")
    fontColor: "#00FF00", // 文字颜色(十六进制或RGB,支持透明度如 `#00FF0080`)
    fontSize: 72,        // 初始字体大小(px)
    minFontSize: 10,     // 最小字体大小
    lineHeight: 50,      // 基础行高(px)
    autoWrapLineHeightMultiplier: 1.2, //换行时的行高倍数
    margin: 20,        // 四周边距(px),会被 `marginBottom` 覆盖
    marginBottom: 40,  // 底部边距(优先级高于 `margin`)
    align: "center",   // 水平对齐:"left" | "center" | "right"
    valign: "middle",  // 垂直对齐:"top" | "middle" | "bottom"
    borderColor: 0xff000099, // 边框颜色(十六进制或十进制,支持透明度)
    borderSize: 2,           // 边框宽度(px)
    backgroundColor: "0080FF33", // 背景色(支持透明度,如 `"rgba(0,128,255,0.2)"`)
    underlineColor: "#00FFFF33", // 下划线颜色(支持透明度)
    underlineSize: 2,            // 下划线粗细(px)
  }
);

textToImage.render().toFile(path.join(__dirname, "image2.png"));

运行后的效果图:

图像属性获取

生成图像后,可以获取各种属性信息,如画布尺寸、渲染时间等。这些属性对于调试和优化图像生成过程非常有用。

let textToImage = new UltimateTextToImage(
  "文本内容",
  {
    width: 400,
  }
);

//等待渲染
await textToImage.render();

// 画布的最终宽度
const width = textToImage.width; 

// 画布的最终高度
const height = textToImage.height;

// 画布的渲染时间
const renderedTime = textToImage.renderedTime;

//包含文本在渲染前的详细测量信息,例如每行文本的尺寸、位置等
const measuredParagraph = textToImage.measuredParagraph; 

获取画布对象
const canvas = textToImage.canvas; 

//是否已执行过渲染操作(render() 方法是否被调用过)。
const hasRendered = textToImage.hasRendered;

运行后的结果:

画布宽度: 929
画布高度: 210
画布渲染时间(ms): 673.5504
文字信息: {
  text: 'abc xyz 0123456789 零一二三四五六七八九',
  width: 890.859375,
  height: 158,
  fontSize: 72,
  fontFamily: 'Sans',
  fontStyle: false,
  fontWeight: false,
  spaceWidth: 22.5,
  boundingHeight: 150,
  boundingWidth: 889.859375,
  paddingTop: -15,
  paddingBottom: 7,
  paddingLeft: 3,
  paddingRight: -1,
  measuredLines: [
    {
      text: 'abc xyz 0123456789 零一二',
      width: 890.859375,
      paddingTop: -15,
      paddingBottom: 14,
      paddingLeft: 1,
      paddingRight: -2,
      nextLineHeight: 86,
      measuredWords: [Array]
    },
    {
      text: '三四五六七八九',
      width: 504,
      paddingTop: -13,
      paddingBottom: 7,
      paddingLeft: 3,
      paddingRight: -1,
      nextLineHeight: 0,
      measuredWords: [Array]
    }
  ]
}
画布对象: [Canvas 929x210]
画布是否渲染 true

动态修改与重新渲染

支持动态修改配置选项并重新渲染图像。这种灵活性使得可以在不创建新实例的情况下调整图像样式。

let textToImage = new UltimateTextToImage(`abc xyz 0123456789 零一二三四五六七八九`, {
  width: 200,
  fontFamily: "Sans", 
})
  .render()
  .toFile(path.join(__dirname, "image1.png"));

textToImage.options.fontFamily = "Comic Sans MS";
textToImage.render().toFile("updated.png");

运行后的结果(Comic Sans MS字体不支持中文):

数据URL输出

除了保存为文件,还可以将图像转换为数据URL格式,便于网页直接使用或嵌入其他应用。

//默认png
let textToImage = new UltimateTextToImage("Hello World").render();
const dataUrlPng = textToImage.toDataUrl(); // image/png by default
console.log(dataUrlPng);


// 0 到 100,其中 100 表示最高质量(无损但文件最大),
//80 表示一个较高的质量但文件大小相对较小。
const dataUrlJpeg = textToImage.toDataUrl("image/jpeg", { quality: 80 });
console.log(dataUrlJpeg);

运行后的效果:

data:image/png;base64,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

缓冲流输出

支持将图像转换为缓冲流,便于进一步处理或传输。提供多种格式选项和压缩参数,平衡质量与大小。

// 图片转buffer
const buffer = textToImage.toBuffer(); // 默认png
//0 表示无压缩(文件最大但最快),9 表示最大压缩
const bufferPng = textToImage.toBuffer("image/png", { compressionLevel: 6 });
// progressive设置渐进式 JPEG 图像,在加载时会逐渐从低分辨率到高分辨率显示
const bufferJpeg = textToImage.toBuffer("image/jpeg", {
   //100:最高质量(几乎无损,文件最大)。0:最低质量(严重失真,文件最小)。
   quality: 80,  
   progressive: true,
 });

画布转换为流并保存为图片

将文本生成的图片转换为可读流,然后通过管道传输到可写流中完成文件保存。

let textToImage = new UltimateTextToImage("Hello World").render();

// 图片转stream
const streamPng = textToImage.toStream(); // 默认生成png格式
const streamJpeg = textToImage.toStream("image/jpeg"); // 指定生成jpeg格式
const out = fs.createWriteStream(path.join(__dirname, "imageE4.png"));
streamPng.pipe(out);

运行后的效果:

多种格式的图像拼接

以下代码展示了如何使用 UltimateTextToImage 库加载多种格式的图像数据(URL、Base64、Buffer、ArrayBuffer),并通过不同方式将这些图像绘制到画布上:

const {
  UltimateTextToImage,
  getCanvasImage
} = require("ultimate-text-to-image");

(async () => {
  const url =
    "https://www.npmjs.com/npm-avatar/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdmF0YXJVUkwiOiJodHRwczovL3MuZ3JhdmF0YXIuY29tL2F2YXRhci8yNjljMGE1MzNiNTQ1MDNkMDg2Y2EwYWJlMzBkODkwNT9zaXplPTEwMCZkZWZhdWx0PXJldHJvIn0.W4Iy2ZRyJ3XX_ju-P_zdYhVlRrONO0ZYJn4iRQw5eFM";
  const buffer = new UltimateTextToImage("repeatX").render().toBuffer();
  const base64 = new UltimateTextToImage("fitY")
    .render()
    .toBuffer()
    .toString("base64");
  const arrayBuffer = new Uint8Array(
    new UltimateTextToImage("repeat").render().toBuffer()
  );

  const canvasImage1 = await getCanvasImage({ url });
  const canvasImage2 = await getCanvasImage({ base64 });
  const canvasImage3 = await getCanvasImage({ buffer });
  const canvasImage4 = await getCanvasImage({ arrayBuffer });

  const textToImage = new UltimateTextToImage("Image Example", {
    width: 600,
    height: 600,
    alignToCenterIfLinesLE: 1,
    fontSize: 72,
    backgroundColor: "#FFFFFF99",
    images: [
      { canvasImage: canvasImage1, layer: -1, repeat: "fit" },
      {
        canvasImage: canvasImage2,
        layer: 0,
        repeat: "fitY",
        x: 10,
        y: 10,
        width: 100,
        height: 100,
      },
      {
        canvasImage: canvasImage3,
        layer: 1,
        repeat: "repeatX",
        sx: -400,
        sy: 100,
        width: 300,
        height: 300,
      },
      {
        canvasImage: canvasImage4,
        layer: 1,
        repeat: "repeat",
        sx: -200,
        sy: -300,
        tx: -50,
        ty: -50,
      },
    ],
  })
    .render()
    .toFile(path.join(__dirname, "image4.png"));
})();

核心功能说明

  1. 图像加载
    代码中使用四种不同来源加载图像:URL、Base64字符串、Buffer对象和ArrayBuffer对象。getCanvasImage函数处理这些不同格式的输入并返回可绘制的图像对象。

  2. 图像绘制参数

    • layer: 控制图像的绘制层级,数值越小越先绘制
    • repeat: 指定图像的重复模式(fit/fitY/repeatX/repeat)
    • x/y: 图像绘制的位置坐标
    • width/height: 控制绘制尺寸
    • sx/sy: 源图像裁剪起始点
    • tx/ty: 目标画布绘制起始点
  3. 输出处理
    最终通过toFile()方法将合成结果保存为PNG文件,也可以使用toBuffer()获取二进制数据用于进一步处理。

运行后的效果图:

文本到图像的渲染控制

动态生成图像时,同时利用 preRenderposRender 回调函数在渲染前后执行自定义逻辑。例如:

let textToImage = new UltimateTextToImage(
  "Rendering",
  {},
  {
    preRender: (canvas) => {
      // 在绘制任何内容前触发(调用 render() 时)
      console.log("before");
      console.log(canvas);
    },
    posRender: (canvas) => {
      // 在绘制完所有文本和图像后触发
      console.log("after");
      console.log(canvas);
    },
  }
).render();

关键点说明

  • preRender:在渲染开始前调用,可用于初始化画布状态或记录调试信息。
  • posRender:在渲染完成后调用,适合对生成的图像进行后处理或保存操作。

混合布局图像

const {
  UltimateTextToImage,
  HorizontalImage,
  VerticalImage,
} = require("ultimate-text-to-image");
const path = require("path");

const textToImage1 = new UltimateTextToImage("Image1", {
  backgroundColor: "#0080FF33",
  fontSize: 60,
});
const textToImage2 = new UltimateTextToImage("Image2 ".repeat(10).trim(), {
  maxWidth: 200,
  backgroundColor: "#00FF0033",
  fontSize: 40,
});

const horizontalImage = new HorizontalImage(
  [
    textToImage1,
    textToImage2,
    new HorizontalImage([
      new UltimateTextToImage("Horizontal 1"),
      new UltimateTextToImage("Horizontal 2", { fontSize: 50 }),
    ]),
    new VerticalImage([
      new UltimateTextToImage("Vertical 1"),
      new UltimateTextToImage("Vertical 2", { fontColor: "#FF0000" }),
    ]),
  ],
  { valign: "bottom", backgroundColor: "#AAAAAA", margin: 100 }
);

horizontalImage.render().toFile(path.join(__dirname, "imageMixed1.jpg"));

功能说明

  • 基础文本图像textToImage1textToImage2 分别生成带有不同背景色和字体大小的文本图像。
  • 嵌套布局HorizontalImageVerticalImage 实现水平和垂直方向的混合布局。
  • 样式配置:通过 valignbackgroundColormargin 参数控制整体对齐、背景色和边距。
  • 输出文件:最终图像通过 render().toFile() 保存为本地文件。

运行后的效果图:


网站公告

今日签到

点亮在社区的每一天
去签到