使用createElementNS创建SVG元素时,对于标准属性(如x、y、stroke)必须始终使用setAttribute(不带命名空间)赋值,如果错误地使用了setAttributeNS,则这些属性将不会被SVG渲染引擎所解析,导致元素虽然可见但无法正常显示。此原则适用于所有SVG元素,无一例外。
先说一个核心结论:SVG 元素创建靠 createElementNS,属性赋值靠 setAttribute —— 命名空间只作用于元素类型,不作用于标准属性。这个原则搞不清楚,很容易踩坑。
在使用 JavaScript 动态操作 SVG 时,一个常见却极易被忽视的陷阱是:元素本身必须在 SVG 命名空间中创建,但它的绝大多数属性(比如 x、y、width、height、stroke、fill 这些)却属于“本地属性”,根本不需要指定命名空间 URI。如果你把两者混为一谈,结果就是——元素在 DOM 里明明能看到,但页面上就是渲染不出来。
长期稳定更新的攒劲资源: >>>点此立即查看<<<
来看看典型的错误写法:
sh_el.setAttributeNS(svgNS, "x", "150"); sh_el.setAttributeNS(svgNS, "y", "150"); sh_el.setAttributeNS(svgNS, "stroke", "blue"); // ……
问题出在哪儿?setAttributeNS(namespace, qualifiedName, value) 这个 API 语法上确实合法,但你把 svgNS(也就是 http://www.w3.org/2000/svg)作为命名空间传进去之后,浏览器会尝试把这些属性注册成带前缀的命名空间属性(比如 svg:x)。而 SVG 渲染引擎只认那些不带前缀的标准属性。所以,尽管 确实插入了 DOM,开发者工具里也能看到它,但关键的位置、尺寸、样式属性其实根本没被解析——元素在,却不显示。
所以正确的做法是:
createElementNS(svgNS, 'rect') 创建元素,这一步必须做,保证元素本身的类型归属 SVG 命名空间。element.setAttribute(name, value),也就是不带命名空间的版本。改完之后长这样:
xyz
setAttributeNS(null, name, value) 在某些场景下也能跑通(null 表示无命名空间),但 setAttribute() 语义更清晰、兼容性更好,是 SVG 属性设置的事实标准,直接用后者就行。xlink:href(已废弃,现代推荐直接用 href)、xml:space 这些才需要用 setAttributeNS,并且要对应正确的命名空间(比如 http://www.w3.org/1999/xlink)。stroke-width),也可以用 rect.style.strokeWidth = "2",注意驼峰命名。不过内联属性更符合 SVG 原生习惯。SVG 元素创建靠 createElementNS,属性赋值靠 setAttribute —— 命名空间仅作用于元素类型,不作用于标准属性。
这一原则同样适用于、、等所有 SVG 元素,是保障动态 SVG 渲染可靠的底层基础。