如何在网页嵌入的SVG中使用自定义字体并动态编辑文本?
自定义字体在img嵌入SVG中失效&动态编辑SVG文本的解决方案
一、问题背景
网页已通过CSS的@font-face加载非预装的Omnes Pro字体,网页内文本显示正常:
@font-face { font-family: "Omnes Pro Bold"; src: url("fonts/Omnes_Pro_Bold.otf") format("opentype"); }
但使用<img>标签嵌入包含该字体文本的SVG时,文本显示为默认字体,无法调用已加载的自定义字体。
同时需要通过JavaScript动态修改SVG中的文本元素,当前SVG是Inkscape创建的文件(而非内嵌<svg>标签),不确定常规方案是否适用,以下是SVG中的文本元素示例:
<text xml:space="preserve" style="font-size:22.5778px;line-height:0.9;font-family:'Omnes Pro';-inkscape-font-specification:'Omnes Pro';direction:rtl;fill:#000000;fill-opacity:1;stroke-width:0.545999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:3.4;stroke-dasharray:1.05833, 0.264583" x="71.448624" y="103.02882" id="text16-2-2" inkscape:label="Second"><tspan sodipodi:role="line" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.87778px;font-family:'Omnes Pro';-inkscape-font-specification:'Omnes Pro, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;direction:ltr;text-anchor:end;stroke-width:0.546" x="73.127846" y="103.02882" id="tspan17-4-3">Second </tspan></text>
已知将文本转为路径的方案不可行(无法动态编辑),核心需求是实现带动态文本的图片,若有更优方案也请告知。
解决方案
1. 解决SVG字体加载问题(img嵌入场景)
用<img>加载SVG时,SVG处于独立文档上下文,无法访问主页面的CSS和字体资源,可通过以下两种方式解决:
方案一:在SVG内部嵌入字体规则
打开SVG文件,在<defs>标签内添加字体加载代码(无<defs>则新建):<defs> <style type="text/css"> @font-face { font-family: "Omnes Pro Bold"; src: url("fonts/Omnes_Pro_Bold.otf") format("opentype"); } @font-face { font-family: "Omnes Pro"; src: url("fonts/Omnes_Pro.otf") format("opentype"); } </style> </defs>注意:字体文件路径需相对于SVG文件位置,确保路径正确。
方案二:将SVG内嵌到页面
把SVG文件内容直接复制到HTML中作为<svg>标签,这样SVG可共享主页面的CSS和字体资源,同时方便后续JS编辑。
2. 动态编辑SVG文本的实现
内嵌SVG场景
直接通过JS选中目标元素修改文本:// 修改tspan文本内容 document.getElementById('tspan17-4-3').textContent = '新的文本内容'; // 如需修改样式,直接操作style属性 document.getElementById('text16-2-2').style.fontFamily = 'Omnes Pro Bold';img加载SVG场景
通过AJAX获取SVG内容,修改后转为Data URL赋值给img的src:fetch('your-svg-file.svg') .then(response => response.text()) .then(svgText => { // 替换目标文本 const updatedSvg = svgText.replace('Second ', '新文本内容'); // 转为Data URL const dataUrl = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(updatedSvg); // 更新img标签 document.getElementById('your-img-id').src = dataUrl; });此方式需确保SVG内部已嵌入字体规则,否则修改后的文本仍会显示默认字体。
3. 替代方案:Canvas绘制
若SVG方案存在局限,可使用Canvas实现带动态文本的图片:
- 利用主页面加载的自定义字体,在Canvas中设置字体并绘制文本
- 可随时通过JS修改文本内容后重新绘制
- 最终可将Canvas转为PNG等图片格式展示
示例代码:
<canvas id="dynamic-canvas" width="200" height="100"></canvas> <script> const canvas = document.getElementById('dynamic-canvas'); const ctx = canvas.getContext('2d'); // 确保字体加载完成后绘制 document.fonts.ready.then(() => { ctx.font = '9.87778px "Omnes Pro"'; ctx.fillStyle = '#000'; ctx.textAlign = 'end'; ctx.fillText('动态文本内容', 73.127846, 103.02882); }); // 动态更新文本的函数 function updateText(newText) { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.fillText(newText, 73.127846, 103.02882); } </script>
内容的提问来源于stack exchange,提问作者Lordimass
相关产品推荐
相关产品推荐

