SVG图形内文本重叠显示兼容性问题排查修复
SVG文本随机断行重叠兼容性问题修复
问题现象
目标实现效果为中心放置1个大圆形节点,周边分布若干小圆形节点,节点间用带动画的虚线连接,圆形内部标注对应文本。在多数设备上显示正常,但部分用户设备上出现圆形内文本随机断行、同位置文本重叠导致无法识别的问题,故障随机出现在不同文本元素上,开发端设备无法复现。
原始问题代码如下:
<svg viewBox="100 0 600 600" width="100%" height="100%" preserveAspectRatio="xMinYMin meet" xmlns="http://www.w3.org/2000/svg"> <style> .draw {stroke-dasharray: 10; animation: dashdraw 4s linear infinite;} @keyframes dashdraw {to {stroke-dashoffset: 200;}} </style> <g> <title>This is our Hub</title> <a xlink:href="#nds"><ellipse id="hub_nds" ry="100" rx="100" cy="300" cx="400" stroke="#000" fill="#fff"/></a> <a xlink:href="#os"><ellipse id="hub_os" ry="50" rx="50" cy="500" cx="400" stroke="#000" fill="#fff"/></a> <a xlink:href="#h"><ellipse id="hub_h" ry="50" rx="50" cy="200" cx="200" stroke="#000" fill="#fff"/></a> <a xlink:href="#ol"><ellipse id="hub_ol" ry="50" rx="50" cy="400" cx="200" stroke="#000" fill="#fff"/></a> <a xlink:href="#hi"><ellipse id="hub_hi" ry="50" rx="50" cy="200" cx="600" stroke="#000" fill="#fff"/></a> <a xlink:href="#fields-ueberschrift28"><ellipse id="hub_top" stroke-dasharray="5,5" ry="50" rx="50" cy="100" cx="400" stroke="#000" fill="#fff"/></a> <a xlink:href="#fields-ueberschrift28"><ellipse id="hub_btm" stroke-dasharray="5,5" ry="50" rx="50" cy="400" cx="600" stroke="#000" fill="#fff"/></a> <a xlink:href="#nds" style="font-weight: normal;"><text xml:space="preserve" text-anchor="start" font-family="inherit" font-size="20" stroke-width="0" id="svg_24" y="296" x="316.07422" stroke="#000" fill="#000000">This is our</text> <text xml:space="preserve" text-anchor="start" font-family="inherit" color="inherit" font-size="20" stroke-width="0" id="svg_28" y="323" x="333.29297" stroke="#000" fill="#000000">Main hub</text></a> <a xlink:href="#h" style="font-weight: normal;"><text xml:space="preserve" text-anchor="start" font-family="inherit" font-size="16" stroke-width="0" id="svg_29" y="205" x="165" stroke="#000" fill="#000000">Here is Hub 1</text></a> <a xlink:href="#hi" style="font-weight: normal;"><text xml:space="preserve" text-anchor="start" font-family="inherit" font-size="16" stroke-width="0" id="svg_30" y="205" x="560" stroke="#000" fill="#000000">Here is Hub 2</text></a> <a xlink:href="#ol" style="font-weight: normal;"><text xml:space="preserve" text-anchor="start" font-family="inherit" font-size="16" stroke-width="0" id="svg_31" y="406" x="162" stroke="#000" fill="#000000">Here is Hub 3</text></a> <a xlink:href="#os" style="font-weight: normal;"><text xml:space="preserve" text-anchor="start" font-family="inherit" font-size="16" stroke-width="0" id="svg_32" y="505" x="361.30469" stroke="#000" fill="#000000">Os</text></a> <line id="line1_btm" class="draw" transform="rotate(-180 520.351 365)" stroke-dasharray="5,5" stroke="#000" y2="380" x2="554.80685" y1="350" x1="485.8947" fill="none"/> <line id="line2_btm" class="draw" stroke-dasharray="5,5" stroke="#000" y2="381.82648" x2="554.35023" y1="351.82648" x1="485.43808" fill="none"/> <line id="line1_h" class="draw" x2="245.89744" y2="219.82051" y1="251.61538" x1="312.30769" stroke="#000" fill="none"/> <line id="line2_h" class="draw" x1="245.44082" y1="221.64699" y2="253.44186" x2="311.85107" stroke="#000" fill="none"/> <line id="line1_ol" class="draw" transform="rotate(-45 279.487 365)" stroke="#000" y2="379.56228" x2="313.94325" y1="350.43772" x1="245.03111" fill="none"/> <line id="line2_ol" class="draw" transform="rotate(-45 279.487 365)" stroke="#000" y1="377.7358" x1="313.48663" y2="348.61124" x2="246" fill="none"/> <line id="line1_hi" class="draw" transform="rotate(135 520.769 236)" y1="252" x1="553.97436" y2="220" x2="487.5641" stroke="#000" fill="none"/> <line id="line2_hi" class="draw" transform="rotate(135 521.226 237.826)" y2="253.82648" x2="554.43098" y1="221.82648" x1="488.02072" stroke="#000" fill="none"/> <line id="line1_top" class="draw" stroke-linecap="undefined" stroke-linejoin="undefined" y2="200.32547" x2="399.35484" y1="150" x1="399.35484" stroke="#000" fill="none"/> <line id="line2_top" class="draw" transform="rotate(180 401.29 175.163)" stroke-linecap="undefined" stroke-linejoin="undefined" y2="200.32547" x2="401.29032" y1="150" x1="401.29032" stroke="#000" fill="none"/> <line id="line1_os" class="draw" stroke-linecap="undefined" stroke-linejoin="undefined" y2="449.99974" x2="399.35484" y1="399.67426" x1="399.35484" stroke="#000" fill="none"/> <line id="line2_os" class="draw" transform="rotate(180 401.29 424.839)" stroke-linecap="undefined" stroke-linejoin="undefined" y2="449.99974" x2="401.29032" y1="399.67426" x1="401.29032" stroke="#000" fill="none"/> </g> </svg>
故障根因
- 所有文本标签都添加了
xml:space="preserve"属性,该属性会要求浏览器保留标签内所有空白字符(包括代码缩进、换行产生的隐形空白)。不同浏览器(尤其是旧版移动端Webview、国内定制内核浏览器)对该属性的解析逻辑不一致,部分浏览器会把这些隐形空白识别为需要折行的空格,触发随机断行。 - 代码中4处连线标签设置了
stroke-linecap="undefined"、stroke-linejoin="undefined"的非法属性值,部分浏览器解析非法SVG属性时会触发渲染树重算异常,连带影响同组内文本元素的位置计算。 - 文本标签未设置明确的折行规则,部分浏览器默认会在图形边界处对文本自动折行,和手动拆分的多行文本位置冲突,导致重叠。
- 字体仅设置为
inherit,未配置兜底字体,当继承到的字体在用户设备上不存在时,浏览器会自动替换 fallback 字体,替换后的字体字宽和设计值不匹配,也会引发布局错乱。
修复方案
- 移除所有
<text>标签上的xml:space="preserve"属性,消除不同浏览器对空白字符的解析差异。 - 删除所有值为
undefined的非法SVG属性,避免渲染引擎解析异常。 - 在全局样式中给文本添加
white-space: nowrap规则,强制所有文本不自动折行。 - 给字体配置通用无衬线字体作为兜底,避免字体替换导致的宽度计算错误。
修复后完整代码
<svg viewBox="100 0 600 600" width="100%" height="100%" preserveAspectRatio="xMinYMin meet" xmlns="http://www.w3.org/2000/svg"> <style> .draw {stroke-dasharray: 10; animation: dashdraw 4s linear infinite;} text {white-space: nowrap; font-family: inherit, system-ui, sans-serif;} @keyframes dashdraw {to {stroke-dashoffset: 200;}} </style> <g> <title>This is our Hub</title> <a xlink:href="#nds"><ellipse id="hub_nds" ry="100" rx="100" cy="300" cx="400" stroke="#000" fill="#fff"/></a> <a xlink:href="#os"><ellipse id="hub_os" ry="50" rx="50" cy="500" cx="400" stroke="#000" fill="#fff"/></a> <a xlink:href="#h"><ellipse id="hub_h" ry="50" rx="50" cy="200" cx="200" stroke="#000" fill="#fff"/></a> <a xlink:href="#ol"><ellipse id="hub_ol" ry="50" rx="50" cy="400" cx="200" stroke="#000" fill="#fff"/></a> <a xlink:href="#hi"><ellipse id="hub_hi" ry="50" rx="50" cy="200" cx="600" stroke="#000" fill="#fff"/></a> <a xlink:href="#fields-ueberschrift28"><ellipse id="hub_top" stroke-dasharray="5,5" ry="50" rx="50" cy="100" cx="400" stroke="#000" fill="#fff"/></a> <a xlink:href="#fields-ueberschrift28"><ellipse id="hub_btm" stroke-dasharray="5,5" ry="50" rx="50" cy="400" cx="600" stroke="#000" fill="#fff"/></a> <a xlink:href="#nds" style="font-weight: normal;"> <text text-anchor="start" font-size="20" stroke-width="0" id="svg_24" y="296" x="316.07422" stroke="#000" fill="#000000">This is our</text> <text text-anchor="start" font-size="20" stroke-width="0" id="svg_28" y="323" x="333.29297" stroke="#000" fill="#000000">Main hub</text> </a> <a xlink:href="#h" style="font-weight: normal;"><text text-anchor="start" font-size="16" stroke-width="0" id="svg_29" y="205" x="165" stroke="#000" fill="#000000">Here is Hub 1</text></a> <a xlink:href="#hi" style="font-weight: normal;"><text text-anchor="start" font-size="16" stroke-width="0" id="svg_30" y="205" x="560" stroke="#000" fill="#000000">Here is Hub 2</text></a> <a xlink:href="#ol" style="font-weight: normal;"><text text-anchor="start" font-size="16" stroke-width="0" id="svg_31" y="406" x="162" stroke="#000" fill="#000000">Here is Hub 3</text></a> <a xlink:href="#os" style="font-weight: normal;"><text text-anchor="start" font-size="16" stroke-width="0" id="svg_32" y="505" x="361.30469" stroke="#000" fill="#000000">Os</text></a> <line id="line1_btm" class="draw" transform="rotate(-180 520.351 365)" stroke-dasharray="5,5" stroke="#000" y2="380" x2="554.80685" y1="350" x1="485.8947" fill="none"/> <line id="line2_btm" class="draw" stroke-dasharray="5,5" stroke="#000" y2="381.82648" x2="554.35023" y1="351.82648" x1="485.43808" fill="none"/> <line id="line1_h" class="draw" x2="245.89744" y2="219.82051" y1="251.61538" x1="312.30769" stroke="#000" fill="none"/> <line id="line2_h" class="draw" x1="245.44082" y1="221.64699" y2="253.44186" x2="311.85107" stroke="#000" fill="none"/> <line id="line1_ol" class="draw" transform="rotate(-45 279.487 365)" stroke="#000" y2="379.56228" x2="313.94325" y1="350.43772" x1="245.03111" fill="none"/> <line id="line2_ol" class="draw" transform="rotate(-4
相关产品推荐
相关产品推荐

