一段内嵌的svg标签,大概这个样子:
<div style="width:600px;height:600px">
<svg width="100%" height="100%">
<defs>
<pattern id="polka-dots" x="0" y="0" width="100" height="100" patternUnits="userSpaceOnUse">
<image xlink:href="./image/face.png" x="0" y="0" width="50" height="50"></image>
</pattern>
</defs>
<rect x="0" y="0" width="100%" height="100%" fill="url(#polka-dots)"></rect>
</svg>
</div>
在矩形框里平铺了部分图片,效果如下:
直接写在html里没问题,但通过js动态创建节点,就怎么也不显示,但是矩形框区域还在。
网上搜一下,大概都是说创建节点的时候,需要指定Namespace,也就是用createElementNS来代替createElement创建节点,Stack Overflow上还有人提供了一段封装好的函数:
function makeSVG(tag, attrs) {
let el= document.createElementNS('http://www.w3.org/2000/svg', tag);
for (let k in attrs) {
el.setAttribute(k, attrs[k]);
}
return el;
}
但使用这个函数创建以后, 还是无法显示,一开始怀疑是pattern的问题——也许不能动态创建pattern?经过仔细验证,最终确认原来是image标签中的xlink:href属性,竟然需要一个跟svg节点不同的Namespace:'http://www.w3.org/1999/xlink'。。。
于是修改创建节点的函数:
function makeSVG(tag, attrs) {
const ns = 'http://www.w3.org/2000/svg';
const xlinkns = 'http://www.w3.org/1999/xlink';
let el= document.createElementNS(ns, tag);
if (tag==='svg'){
el.setAttribute('xmlns:xlink', xlinkns);
}
for (let k in attrs) {
if (k === 'xlink:href') {
el.setAttributeNS(xlinkns, k, attrs[k]);
} else {
el.setAttribute(k, attrs[k]);
}
}
return el;
}
这下可以正常使用了,调用示例如下:
window.addEventListener('load', function(){
const svgtest = document.getElementById('svg-test');
let svg = makeSVG('svg');
svg.style.width='100%';
svg.style.height='100%';
let defs = makeSVG('defs');
let pattern = makeSVG('pattern', {id:'polka-dots',x:'0',y:'0',width:'100',height:'100',patternUnits:'userSpaceOnUse'});
let image = makeSVG('image',{'xlink:href':'./image/face.png', width:'50', height: '50', x:'0', y:'0'});
let rect = makeSVG('rect',{x:'0',y:'0',width:'100%',height:'100%',fill:'url(#polka-dots)'});
// image.onload = function(){
// };
defs.appendChild(pattern);
pattern.appendChild(image);
svg.appendChild(defs);
svg.appendChild(rect);
svgtest.appendChild(svg);
});
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。