Figma插件获取混合字体样式报错:Cannot unwrap symbol 解决方法
解决Figma插件选中混合字体元素时postMessage报错“Cannot unwrap symbol”的问题
当Figma插件尝试提取选中元素的字体信息,且选中包含混合字体样式的文本节点时,会触发以下错误:
figma_app.min.js.br:5 Error: in postMessage: Cannot unwrap symbol
at (PLUGIN_477_SOURCE:26)
错误原因
混合字体的文本节点(同一TEXT节点内存在多种字体样式)中,node.fontName不会返回常规的FontName对象,而是返回一个Symbol类型的值。postMessage仅支持传递可JSON序列化的数据,Symbol无法被序列化,因此触发报错。
解决方案
需要针对混合字体节点做特殊处理:通过getRangeFontName遍历文本的每个字符范围,逐个获取对应位置的字体信息,而非直接读取node.fontName。同时,字重信息也需要用getRangeFontWeight逐个范围获取,避免混合字体时node.fontWeight失效。
修改后的完整代码
选择监听逻辑(无需修改)
figma.on("selectionchange", () => { const selectedNodes = figma.currentPage.selection; if (selectedNodes && selectedNodes.length > 0) { const fontsInSelection = getFontsFromSelection(selectedNodes); figma.ui.postMessage({ type: "fontList", fonts: fontsInSelection }); } else { figma.ui.postMessage({ type: "noElementSelected" }); } });
字体提取函数(核心修改)
function getFontsFromSelection(selection: ReadonlyArray<SceneNode>) { const fontsMap = new Map(); function processNode(node: SceneNode) { if (node.type === "TEXT") { const textLength = node.characters.length; // 遍历每个字符范围获取字体,处理混合字体场景 for (let i = 0; i < textLength; i++) { try { const font = node.getRangeFontName(i, i + 1) as FontName; if (!font) continue; const fontFamily = font.family; const fontStyle = font.style; const fontWeight = node.getRangeFontWeight(i, i + 1) || ""; if (!fontsMap.has(fontFamily)) { fontsMap.set(fontFamily, new Set()); } const stylesSet = fontsMap.get(fontFamily); // 生成唯一key解决对象无法去重的问题 const styleKey = `${fontStyle}_${fontWeight}`; stylesSet.add({ style: fontStyle, weight: fontWeight, key: styleKey }); } catch (e) { // 跳过异常范围,避免函数中断 continue; } } } else if (node.type === "GROUP" || node.type === "FRAME") { for (const childNode of (node as GroupNode | FrameNode).children) { processNode(childNode); } } } for (const node of selection) { processNode(node); } const fonts = []; // 对字体样式去重 for (const [fontFamily, fontStyles] of fontsMap) { const uniqueStyles = Array.from(fontStyles).reduce((acc, curr) => { if (!acc.some(item => item.key === curr.key)) { acc.push({ style: curr.style, weight: curr.weight }); } return acc; }, [] as {style: string, weight: string | number}[]); fonts.push({ family: fontFamily, styles: uniqueStyles }); } return fonts; }
关键修改点说明
- 替换字体获取方式:用
getRangeFontName(i, i+1)逐个字符范围获取字体,避免混合字体时node.fontName返回Symbol的问题。 - 可靠获取字重:用
getRangeFontWeight获取对应范围的字重,替代直接读取node.fontWeight(混合字体场景下该属性无效)。 - 样式去重处理:通过生成唯一key解决Set中对象因引用不同无法去重的问题,确保最终返回的字体样式不重复。
- 异常容错:增加try-catch块跳过极少数无法获取字体的字符范围,避免整个函数执行中断。
内容的提问来源于stack exchange,提问作者pinata
相关产品推荐
相关产品推荐

