使用PDFMake导出SVG时箭头符号无法正常显示问题求助
问题:Highcharts SVG导出PDF时特殊箭头符号显示异常
在使用Highcharts生成图表SVG后,通过PDFMake导出为PDF时遇到符号显示问题:绿色向上箭头▲(Unicode U+25B2)在PDF中显示为绿色方框,但使用↑(Unicode U+2191)时则显示正常。
Highcharts箭头相关代码
series: [ { type: 'waterfall', upColor: Highcharts.getOptions().colors[2], color: Highcharts.getOptions().colors[3], dataLabels: { enabled: true, inside: false, style: { textOutline:'none' }, formatter() { const { value=null } = getValue(this.key); const isZeroVal = !this.y; const zeroValCss = isZeroVal ? 'margin-top: -8px;': ''; let greenArrow = '<span style="color: green;">▲</span>'; let redArrow = '<span style="color: red;">▼</span>'; return ` <div style='text-align:center;color:black;${zeroValCss}'> ${isZeroVal ? (!fullBars.includes(this.point.code) ? 'No Change' : value): value} ${value?.includes('+') ? greenArrow : value?.includes('-') ? redArrow : ''} </div> `; } }, data: scoreData?.filter(pb => !nonWaterfall.includes(pb.code)) || [], pointPadding: 0 } ] };
PDFMake导出代码
import util from '../utilities/credit-report-util.js'; import pdfUtil from '../utilities/pdfmake-util'; const scoreBreakDown = () => [pdfUtil.table({ widths: ['100%'], body: [ [{ text: 'Score Breakdown', style: 'rgPlusBlack', border: [true, true, true, false], margin: [0, 2, 0, 0] }], [{ svg: util.getSVGToEmbedPDF($('.rgPlus-ScoreBreakdownChart .highcharts-container svg')), border: [true, false, true, true], alignment: 'center', margin: [0, 4, 0, 0], width: 400, height: 85 }] ] }, { defaultBorder: false, borderWidth: 1, borderColor: borderColor(true) })]; const getSVGToEmbedPDF = (svgelm, viewBoxHeight, viewBoxWidth, width = '100%', height = '100%', trimSvg = false, useStrokeForBold = false, preserveAspectRatio = false) => { if (svgelm.length) { const isBMChartSvg = svgelm.closest('.ca-m-bench-chart')?.length > 0; let cloneSvgElm = svgelm.clone(true); const actualWidth = cloneSvgElm.attr('width'); const actualHeight = cloneSvgElm.attr('height'); cloneSvgElm[0].setAttribute('viewBox', `0 0 ${viewBoxWidth || actualWidth} ${viewBoxHeight || actualHeight}`); cloneSvgElm.attr('width', width); cloneSvgElm.attr('height', height); if (preserveAspectRatio) cloneSvgElm[0].setAttribute('preserveAspectRatio', `none`); replaceImageTagToSVG(cloneSvgElm, isBMChartSvg); if (useStrokeForBold) addStrokeForBold(cloneSvgElm); if (trimSvg) cloneSvgElm[0].setAttribute('preserveAspectRatio', 'xMinYMin slice'); return new XMLSerializer().serializeToString(cloneSvgElm[0]); } return emptySvg; //Fallback in case svg is not created };
异常SVG示例(▲显示为方框)
<svg> <g class="highcharts-label highcharts-data-label highcharts-data-label-color-undefined" data-z-index="1" transform="translate(508,48)"><text x="5" data-z-index="1" y="16" style="color:#000000;font-size:11px;font-weight:bold;fill:#000000;"><tspan style="text-align:center;fill:black;"> +9 <tspan style="fill: green;">▲</tspan> </tspan></text></g> </svg>
正常SVG示例(↑显示正常)
<svg> <g class="highcharts-label highcharts-data-label highcharts-data-label-color-undefined" data-z-index="1" transform="translate(508,48)"> <text x="5" data-z-index="1" y="16" style="color:#000000;font-size:11px;font-weight:bold;fill:#000000;"> <tspan style="text-align:center;fill:black;"> +9 <tspan style="fill: green;">↑</tspan> </tspan> </text> </g> </svg>
解决方法
原因分析
▲(U+25B2)属于方块元素类符号,PDFMake依赖的底层渲染引擎默认使用的字体可能不包含该符号的字形,导致无法渲染显示为方框;而↑(U+2191)属于常用箭头符号,多数基础字体都包含其字形。
方案1:替换为兼容符号
直接将代码中的▲(▲)替换为↑(↑),或使用其他PDF渲染引擎支持的箭头符号,如⇗(↗)等。修改Highcharts formatter中的箭头定义:
let greenArrow = '<span style="color: green;">↑</span>'; let redArrow = '<span style="color: red;">↓</span>';
方案2:嵌入包含目标符号的字体
如果必须使用▲符号,需在PDFMake中嵌入支持该符号的字体(如Arial Unicode MS、Noto Sans等):
- 将字体文件(如
.ttf)放入项目目录 - 在PDFMake配置中注册字体:
pdfMake.fonts = { NotoSans: { normal: 'NotoSans-Regular.ttf', bold: 'NotoSans-Bold.ttf', italics: 'NotoSans-Italic.ttf', bolditalics: 'NotoSans-BoldItalic.ttf' } };
- 修改Highcharts dataLabels的style,添加字体设置:
style: { textOutline:'none', fontFamily: 'NotoSans' }
方案3:将符号转为SVG图形
不使用文本符号,直接生成SVG箭头图形避免字体依赖:
// 替换箭头文本为SVG图形 let greenArrow = '<svg width="10" height="8"><polygon points="5,0 0,8 10,8" fill="green"/></svg>'; let redArrow = '<svg width="10" height="8"><polygon points="5,8 0,0 10,0" fill="red"/></svg>';
内容的提问来源于stack exchange,提问作者user13677598
相关产品推荐
相关产品推荐

