使用JavaScript创建可缩放SVG时innerHTML无法插入polygon问题
问题产生原因
- 核心原因是
innerHTML赋值时浏览器会立刻对传入的字符串做DOM解析,不会等待后续拼接操作。你第一次执行svgTriangle[0].innerHTML = "<polygon points='";时,传入的是不完整的标签片段,浏览器会自动补全标签结构,直接生成一个完整的空polygon节点,后续你通过+=追加的内容不会进入polygon的points属性,只会成为SVG节点下的无效文本节点,自然无法生成正确的三角形。 - 额外注意:SVG属于独立的XML命名空间,和普通HTML DOM的解析规则存在差异,分段拼接
innerHTML操作SVG内部节点的写法本身就极容易出现解析异常,不推荐使用。
修复方案
方案1:最小改动,一次性写入完整HTML字符串
不要分段修改innerHTML,先把完整的polygon标签字符串拼接完成后,再一次性赋值给SVG的innerHTML,避免浏览器中途解析不完整标签:
var svgTriangle = document.getElementsByClassName("svg-triangle"); var bgTrianglePoints; function updateOnResize() { bgTrianglePoints = [ [0, 0], [window.innerWidth * 0.76, 0], [window.innerWidth * .16, window.innerHeight * 1.2], [0, window.innerHeight * 1.2] ]; // 先拼接完所有坐标点 let pointsContent = ""; for (var i = 0; i < bgTrianglePoints.length; i++) { pointsContent += bgTrianglePoints[i][0] + "," + bgTrianglePoints[i][1] + " "; } // 一次性写入完整标签 svgTriangle[0].innerHTML = `<polygon points="${pointsContent}" fill="red" />`; } window.onresize = updateOnResize; updateOnResize();
对应的CSS不需要额外修改,如果你想把填充色写在CSS里,保留原来.svg-triangle的fill: red规则即可,SVG子元素会继承fill属性。
方案2:标准DOM操作(更稳妥,性能更好)
使用SVG专属的DOM API创建节点,从根源上避免innerHTML的解析问题,后续resize只需要更新points属性,不需要重复销毁创建节点:
// 获取SVG节点 const svgTriangle = document.querySelector(".svg-triangle"); // 创建SVG命名空间下的polygon元素,必须传入正确的命名空间才能被正常渲染 const polygon = document.createElementNS("http://www.w3.org/2000/svg", "polygon"); polygon.setAttribute("fill", "red"); svgTriangle.appendChild(polygon); function updateOnResize() { const bgTrianglePoints = [ [0, 0], [window.innerWidth * 0.76, 0], [window.innerWidth * .16, window.innerHeight * 1.2], [0, window.innerHeight * 1.2] ]; // 拼接坐标字符串 const pointsStr = bgTrianglePoints.map(point => point.join(",")).join(" "); // 仅更新points属性 polygon.setAttribute("points", pointsStr); } window.onresize = updateOnResize; updateOnResize();
两种方案都可以实现窗口大小变化时三角形自适应调整的效果,第二种方案性能更优,也不会出现命名空间、标签解析类的异常,更推荐使用。
内容的提问来源于stack exchange,提问作者Jonathan Mulvahill
相关产品推荐
相关产品推荐

