
Fabric.js 默认在对象被选中时自动将其置顶,导致文本被图片遮挡;启用 preserveObjectStacking: true 选项可禁用该行为,确保图层顺序严格按添加/调整顺序维持。
fabric.js 默认在对象被选中时自动将其提升至顶层(即调用内部等效的 `bringtofront`),这是其交互设计的一部分——便于用户编辑当前选中对象。但这一机制会破坏你精心维护的图层结构,例如希望标题文字始终显示在所有图片、图形之上时,一旦点击图片,文字就会被“压”到下方,造成视觉遮挡。本文将为你提供稳定、可靠且符合 fabric.js 最佳实践的解决方案。
核心解决方案:启用 preserveObjectStacking
Fabric.js 提供了内置配置项 preserveObjectStacking,只需在初始化 Canvas 时将其设为 true,即可彻底禁用“选中即置顶”的默认行为。此后,所有对象的 Z 轴顺序(即渲染层级)将严格遵循其在 canvas._objects 数组中的位置——先添加的在下,后添加或显式调用 bringToFront() 的在上,且不会因交互(如点击、选择)而意外改变。
const canvas = new fabric.Canvas('spacebar-canvas', {
preserveObjectStacking: true // ✅ 关键配置:锁定图层顺序
});⚠️ 注意:此选项必须在 new fabric.Canvas(...) 实例化时传入,无法在运行时动态开启或关闭。若已创建 canvas 实例,需重新初始化(通常不推荐)或确保从一开始就启用。
配合手动层级控制,实现“文本永远在最前”
仅启用 preserveObjectStacking 还不够——你仍需确保文本对象本身处于顶层位置。推荐在每次创建或更新文本时,显式调用 canvas.bringToFront(textObject) 并立即渲染:
function updateText() {
const textInput = document.getElementById('text-input').value;
if (!textInput) return;
// 移除旧文本(如有)
canvas.getObjects().forEach(obj => {
if (obj.type === 'text') canvas.remove(obj);
});
// 创建新文本
const textObject = new fabric.Text(textInput, {
left: canvas.width / 2,
top: canvas.height / 2,
fontSize: 18,
fontFamily: document.getElementById('font-family').value,
fontWeight: document.getElementById('font-weight').value,
fontStyle: document.getElementById('italic').checked ? 'italic' : 'normal',
fill: document.getElementById('text-color').value,
originX: 'center',
originY: 'center'
});
canvas.add(textObject);
canvas.bringToFront(textObject); // ✅ 强制置于最前
canvas.renderAll(); // ✅ 立即刷新渲染
}同时,在添加图片时,避免误用 sendToBack()(它会把图片塞到底层,可能影响背景 SVG 渲染)。如需图片默认在文字之下,应确保图片先于文本添加;若需灵活控制,可用 canvas.sendBackwards(img) 或 canvas.bringForward(img) 精细调整,但前提是 preserveObjectStacking: true 已启用。
补充建议与注意事项
- 不要依赖 canvas.getActiveObject() 后手动 bringToFront():选中逻辑已被 preserveObjectStacking 屏蔽,无需额外干预。
- 慎用 canvas.forEachObject(...) 删除 + 重建:频繁销毁重建对象会影响性能,建议复用文本实例并仅更新属性(如 textObject.set({ text: newText }))。
- 背景处理:你代码中使用 setBackgroundImage() 加载 SVG,它天然位于所有对象之下,无需额外管理层级。
- 调试技巧:可通过 console.log(canvas._objects.map(o => o.type)) 查看当前对象栈顺序,验证文本是否确实在末尾(即最上层)。
通过 preserveObjectStacking: true + 显式 bringToFront() 的组合策略,你既能获得 Fabric.js 完整的交互能力,又能完全掌控视觉层级——让标题文字真正“稳坐高位”,无论用户点击多少次图片,它都岿然不动。










