一个 Canvas 库发了新版本,最值得注意的不是新功能,而是它修了一个 CVE。Fabric.js 7.4.0 修复了 CVE-2026-44311,如果你正在生产环境用 Fabric.js,这个版本不是"可选升级",而是"必须跟进"。
Fabric.js 本身做的事情很明确:在原生 HTML5 Canvas 上架一层可交互的对象模型,让你不再跟像素级 API 死磕,而是像操作 DOM 元素一样操作画布上的图形——拖拽、缩放、旋转、分组,甚至导出 SVG。下面快速拆一下它的核心能力,再给一个可以直接跑的实战示例。
CVE-2026-44311:为什么这次升级不能拖
Fabric.js 长期支持从 SVG 和 JSON 加载对象,这是它最方便的功能之一,也是安全隐患的入口。CVE-2026-44311 涉及的对象加载路径,在解析外部输入时存在注入风险——恶意构造的 SVG 或 JSON 数据可以在渲染过程中执行非预期代码。
影响范围:任何允许用户上传 SVG/JSON 并通过 fabric.loadSVGFromString、fabric.Object.fromObject 等方法直接解析渲染的场景。如果你的应用只做本地硬编码图形渲染、不接受外部输入,风险较低,但仍然建议升级,因为后续版本可能在此基础上做更多安全加固。
升级方式:
npm install fabric@7.4.0
# 或
yarn add fabric@7.4.0
升级后跑一遍现有测试,重点关注 SVG 加载和 JSON 反序列化相关用例,确认渲染结果无变化即可。
对象模型:从像素操作到"画布上的 DOM"
原生 Canvas API 是即时模式的——画完就完,没有对象概念。你想移动一个矩形?得清空画布、重算坐标、重新绘制。Fabric.js 改成保留模式:每个图形是一个 fabric.Object 实例,有属性、有事件、有状态。
核心类一览:
| 类 | 用途 |
|---|---|
fabric.Rect |
矩形 |
fabric.Circle |
圆形 |
fabric.Path |
自定义路径(SVG path data) |
fabric.Text / fabric.Textbox |
文本与可编辑文本框 |
fabric.Group |
对象分组,整体操作 |
fabric.Image |
图片对象 |
每个对象自带交互:选中后出现控制手柄,拖拽移动、角落缩放、顶部旋转,全部内置,不需要自己写 hit detection 和 transform 逻辑。
Canvas-to-SVG:双向转换是杀手级功能
Fabric.js 不只是"画出来",它还能"存下来"。canvas.toSVG() 输出完整 SVG 文档,canvas.toJSON() 输出可序列化的 JSON。反过来,fabric.loadSVGFromString() 和 fabric.Object.fromObject() 能把数据还原成画布对象。这让它在设计工具、白板协作、模板编辑等场景里几乎是标配选择。
安全提醒正是落在这一环——反序列化外部输入时务必升级到 7.4.0,并在业务层做输入校验。
实战:5 分钟搭一个可交互图形编辑画布
下面这段代码可以直接放进任意 HTML 文件运行,不需要构建工具。它创建一个画布,添加矩形、圆形、文本三个对象,全部可拖拽、缩放、旋转,并演示 SVG 导出。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Fabric.js 7.4.0 Demo</title>
<!-- 从 CDN 加载 7.4.0,生产环境建议用本地打包 -->
<script src="https://cdn.jsdelivr.net/npm/fabric@7.4.0/dist/fabric.min.js"></script>
<style>
body { margin: 20px; font-family: sans-serif; }
canvas { border: 1px solid #ccc; }
#svg-output { margin-top: 16px; white-space: pre-wrap; font-size: 12px; background: #f5f5f5; padding: 12px; max-height: 300px; overflow: auto; }
</style>
</head>
<body>
<h2>Fabric.js 交互画布 Demo</h2>
<canvas id="c" width="600" height="400"></canvas>
<br>
<button id="export-btn">导出 SVG</button>
<button id="add-circle-btn">添加随机圆形</button>
<div id="svg-output"></div>
<script>
// 初始化画布
const canvas = new fabric.Canvas('c', {
backgroundColor: '#fafafa',
selection: true // 允许框选多个对象
});
// 矩形
const rect = new fabric.Rect({
left: 100,
top: 80,
width: 120,
height: 80,
fill: '#e74c3c',
rx: 8, ry: 8, // 圆角
strokeWidth: 2,
stroke: '#c0392b'
});
// 圆形
const circle = new fabric.Circle({
left: 300,
top: 120,
radius: 50,
fill: '#3498db',
strokeWidth: 2,
stroke: '#2980b9'
});
// 可编辑文本
const text = new fabric.Textbox('Fabric.js', {
left: 180,
top: 250,
width: 200,
fontSize: 28,
fill: '#2c3e50',
fontWeight: 'bold',
editable: true // 双击可编辑文字
});
canvas.add(rect, circle, text);
canvas.renderAll();
// 导出 SVG
document.getElementById('export-btn').addEventListener('click', () => {
const svg = canvas.toSVG();
document.getElementById('svg-output').textContent = svg;
});
// 添加随机圆形
document.getElementById('add-circle-btn').addEventListener('click', () => {
const r = new fabric.Circle({
left: Math.random() * 500,
top: Math.random() * 300,
radius: 20 + Math.random() * 40,
fill: `hsl(${Math.random() * 360}, 70%, 60%)`,
opacity: 0.8
});
canvas.add(r);
canvas.renderAll();
});
</script>
</body>
</html>
打开这个页面后,你可以直接用鼠标拖动图形、拉角缩放、旋转,双击文本框编辑文字,点按钮导出 SVG 或添加新圆形。这就是 Fabric.js 的核心价值——原生 Canvas 要写几百行才能实现的交互,这里几行配置就搞定。
升级与采用建议
- 已经在用 Fabric.js 的项目:立即升级到 7.4.0,重点验证 SVG/JSON 加载路径,确认 CVE 修复不影响现有渲染逻辑。
- 新项目评估:如果需求是"画布上可交互的图形编辑",Fabric.js 仍是同类库里生态最成熟、API 最稳定的选项。但要注意它体积不小(min 版约 300KB+),如果只需要静态图表渲染,Chart.js 或 D3 可能更轻。
- 安全底线:任何接受用户上传 SVG/JSON 的场景,升级后仍应在业务层做白名单校验——库修了已知漏洞,不代表未来不会有新的注入路径。
- TypeScript 支持:Fabric.js 7.x 已内置类型定义,不再需要额外安装
@types/fabric。
Fabric.js 不是什么新潮框架,它是一个已经跑了十多年的老牌 Canvas 库,7.x 系列在逐步清理历史包袱(旧 API 废弃、类型完善、安全加固)。这次 7.4.0 的核心动作就是堵漏洞,功能上没有大变化,但安全补丁本身就是最好的升级理由。