基于 fabric 实现矢量文字处理

878 阅读3分钟

前言

因为目前有时间了,所以在整理一下自己这几年写过的一些东西的相关文档,准备把一些东西改一下发出来,有的内容可能并不复杂,甚至有点浅显,但是也是对自己这几年的一些复盘和总结了

原创文章,全文唯一
如果内容有帮助请不要吝啬您的点赞收藏哦
有转载需求的请跟我确认

什么是矢量文字

image.png

矢量文字中每一个字形是通过数学曲线来描述的,包含了字形边界上的关键点、连线的导数信息等。
字体的渲染引擎通过读取这些数学矢量,并进行一定的数学运算来进行渲染。
上面是 xtool 的矢量文字演示,所有的字体是通过路径线条组成的,在 xtool 2.0 的版本中还能对字体的路径进行任意方式的编辑和操作
矢量文字的优点在于其实际尺寸可以任意缩放而不变形、变色。这是因为它基于数学曲线的描述方式,使得字体在放大或缩小时都能保持边缘的光滑和清晰。
矢量文字在需要高质量文字渲染的场合非常有用,如印刷、出版、广告设计、激光雕刻等。在这些领域,文字需要被放大或缩小以适应不同的版面或媒介,而矢量文字能够确保文字在任何尺寸下都保持清晰和美观。

方案调研

方案对比

说明fontkitopentype.jsTypr.jsvectorize-text.js
字体支持Supports TrueType (.ttf), OpenType (.otf), WOFF, WOFF2, TrueType Collection (.ttc),and Datafork TrueType (.dfont) font filesSupport for WOFF, OTF, TTF (both with TrueType glyf and PostScript cff outlines)TTF, OTF, TTC 号称成功解析了 3000 多种字体(opentype.js 对其中许多字体都存在问题)文本字符串,不支持字体文件
使用环境node / 浏览器node / 浏览器浏览器浏览器
大小6.13mb3.78mb70kb391kb
易用性API 相对复杂,需要一定的学习成本易用易用易用
高级字体操作支持不支持未知不支持
字体变换支持支持不支持未知不支持
star / fork1.4k / 2074.3K / 465894 / 73306 / 21
性能在处理大型字体文件和复杂矢量路径时,性能表现优异,适合对性能要求较高的场景在处理大型字体文件或复杂矢量路径时,性能可能会有所限制号称比 opentype.js 快2 到5倍未知
是否支持字距调整支持坐标操作支持可控制坐标不支持
支持复合字形支持支持未知不支持
支持彩色字体支持支持支持不支持


方案验证

经过上面的方案对比,我们根据自己需要的场景首先验证 fontkit 是否符合我们的需求

fontKit

import fontkit from 'fontkit';

// 使用 fetch API 加载字体文件
fetch('path/to/font.ttf')
  .then(response => response.arrayBuffer())
  .then(buffer => {
    const font = fontkit.create(new Uint8Array(buffer));
    const glyph = font.glyphForCodePoint(65); // 'A'
    console.log(glyph.path.toSVG());
  })
  .catch(error => console.error('字体加载失败:', error));

opentype.js

// 使用 fetch API 加载字体文件
fetch('path/to/font.ttf')
  .then(response => response.arrayBuffer())
  .then(buffer => {
    const font = opentype.parse(buffer);
    const path = font.getPath('Hello, World!', 0, 150, 72);
    const svg = path.toSVG();
    document.getElementById('svg-container').innerHTML = svg;
  })
  .catch(error => console.error('字体加载失败:', error));

无论是使用 fontKit 还是 opentype.js 对于我们需求中的十来种字体都能提取到合适的字体轮廓,所以我们考虑到后期可能存在的业务需求变更,我们采用了性能更好,功能更多的 fontkit 来实现我们的功能