2

一段内嵌的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>

在矩形框里平铺了部分图片,效果如下:
image.png

直接写在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);
});

songofhawk
303 声望24 粉丝