【问题标题】:SVG Linear Gradient SVG BackgroundSVG 线性渐变 SVG 背景
【发布时间】:2021-03-09 08:02:13
【问题描述】:

我正在尝试使用将从 JavaScript 动态创建的 SVG 作为另一个 SVG 上的背景图像。这在对象的填充颜色是纯色时有效,但在我尝试使用线性渐变时无效。运行代码以查看示例。请帮忙弄清楚如何使用线性渐变!

        const createElement = (tag, attributes) => {
            const element = document.createElement(tag);
            if (attributes) Object.keys(attributes).forEach(key => element.setAttribute(key, attributes[key]));
            return element;
        }

        // Create background for first SVG using solid color fill:
        const svg3bg = createElement('svg', { xmlns: 'http://www.w3.org/2000/svg', viewBox: '0 0 50 50', width: 50, height: 50 });
        svg3bg.appendChild(createElement('circle', { cx: 25, cy: 25, r: 20, fill: '#00F' }));
        const svg3 = document.getElementById('svg3');
        svg3.style.backgroundImage = `url('data:image/svg+xml,${svg3bg.outerHTML.replace(/\#/g, '%23')}')`; // This does not display unless I replace the # signs with a hex code.
        svg3.style.backgroundColor = 'palegreen';

        // Create background for second SVG using linear gradient fill:
        const svg4bg = createElement('svg', { xmlns: 'http://www.w3.org/2000/svg', viewBox: '0 0 50 50', width: 50, height: 50 });
        const lg4 = svg4bg.appendChild(createElement('linearGradient', { id: "lg4" }))
        lg4.appendChild(createElement('stop', { offset: "0%", 'stop-color': '#d67ef5' }))
        lg4.appendChild(createElement('stop', { offset: "50%", 'stop-color': '#2b78ba' }))
        lg4.appendChild(createElement('stop', { offset: "100%", 'stop-color': '#4d79a9' }))
        svg4bg.appendChild(createElement('circle', { cx: 25, cy: 25, r: 20, fill: 'url(#lg4)' }));
        const svg4 = document.getElementById('svg4');
        svg4.style.backgroundImage = `url('data:image/svg+xml,${svg4bg.outerHTML.replace(/\#/g, '%23')}')`;
        svg4.style.backgroundColor = 'palegreen';
    This shows an SVG using another SVG (generated from JavaScript) of blue dots as its background image:
    <div id="div3">
        <svg id="svg3" iewBox="0 0 100 100" style="width: 150; height: 150;">
            <rect x="10" y="10" width="80" height="80" style="stroke: black; fill: none; stroke-width: 4"></rect>
        </svg>
    </div><br>
    When trying to do the same thing with a linear gradient to fill the object instead of a solid color, it does not
    display:
    <div id="div4">
        <svg id="svg4" iewBox="0 0 100 100" style="width: 150; height: 150;">
            <rect x="10" y="10" width="80" height="80" style="stroke: black; fill: none; stroke-width: 4"></rect>
        </svg>
    </div><br>
    This shows what the background image with the linear gradient should look like:
    <div id="div5">
        <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 50 50" width="50" height="50">
            <lineargradient id="lg5">
                <stop offset="0%" stop-color="#d67ef5"></stop>
                <stop offset="50%" stop-color="#2b78ba"></stop>
                <stop offset="100%" stop-color="#4d79a9"></stop>
            </lineargradient>
            <circle cx="25" cy="25" r="20" fill="url(#lg5)"></circle>
        </svg>
    </div>

【问题讨论】:

    标签: javascript svg background linear-gradients


    【解决方案1】:

    纠正所有错别字后,我觉得还可以。

    • viewBox 在某些地方缺少 v
    • CSS 尺寸中缺少必需的单位
    • 使用 createElementNS 创建 SVG 元素并使用 XML 序列化程序而不是 HTML 序列化程序在输出中获取命名空间。
    • 虽然在这种情况下没有必要,但我已正确修复 URI 编码,而不是使用替换

    const createElement = (tag, attributes) => {
                const element = document.createElementNS('http://www.w3.org/2000/svg', tag);
                if (attributes) Object.keys(attributes).forEach(key => element.setAttribute(key, attributes[key]));
                return element;
            }
    
            let s = new XMLSerializer();
            // Create background for first SVG using solid color fill:
            const svg3bg = createElement('svg', { viewBox: '0 0 50 50', width: 50, height: 50 });
            svg3bg.appendChild(createElement('circle', { cx: 25, cy: 25, r: 20, fill: '#00F' }));
            const svg3 = document.getElementById('svg3');
            svg3.style.backgroundImage = `url('data:image/svg+xml,${encodeURIComponent(s.serializeToString(svg3bg))}')`;
            svg3.style.backgroundColor = 'palegreen';
    
            // Create background for second SVG using linear gradient fill:
            const svg4bg = createElement('svg', { viewBox: '0 0 50 50', width: 50, height: 50 });
            const lg4 = svg4bg.appendChild(createElement('linearGradient', { id: "lg4" }))
            lg4.appendChild(createElement('stop', { offset: "0%", 'stop-color': '#d67ef5' }))
            lg4.appendChild(createElement('stop', { offset: "50%", 'stop-color': '#2b78ba' }))
            lg4.appendChild(createElement('stop', { offset: "100%", 'stop-color': '#4d79a9' }))
            svg4bg.appendChild(createElement('circle', { cx: 25, cy: 25, r: 20, fill: 'url(#lg4)' }));
            const svg4 = document.getElementById('svg4');
            svg4.style.backgroundImage = `url('data:image/svg+xml,${encodeURIComponent(s.serializeToString(svg4bg))}')`;
            svg4.style.backgroundColor = 'palegreen';
    This shows an SVG using another SVG (generated from JavaScript) of blue dots as its background image:
        <div id="div3">
            <svg id="svg3" viewBox="0 0 100 100" style="width: 150px; height: 150px;">
                <rect x="10" y="10" width="80" height="80" style="stroke: black; fill: none; stroke-width: 4"></rect>
            </svg>
        </div><br>
        When trying to do the same thing with a linear gradient to fill the object instead of a solid color, it does not
        display:
        <div id="div4">
            <svg id="svg4" viewBox="0 0 100 100" style="width: 150px; height: 150px;">
                <rect x="10" y="10" width="80" height="80" style="stroke: black; fill: none; stroke-width: 4"></rect>
            </svg>
        </div><br>
        This shows what the background image with the linear gradient should look like:
        <div id="div5">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" width="50" height="50">
                <linearGradient id="lg5">
                    <stop offset="0%" stop-color="#d67ef5"></stop>
                    <stop offset="50%" stop-color="#2b78ba"></stop>
                    <stop offset="100%" stop-color="#4d79a9"></stop>
                </linearGradient>
                <circle cx="25" cy="25" r="20" fill="url(#lg5)"></circle>
            </svg>
        </div>

    【讨论】:

    • 有趣的是,我正在尝试 createElementNS,但是当我也在使用 outerHTML 时,它没有在输出中包含 xmlns 属性。然后在使用 createElementNS 时,也不允许我使用 setAttribute 或 setAttributeNS 添加 xmlns 属性。所以这就是我切换到 createElement 的原因,所以我可以手动添加 xmlns 属性。但是我现在看到,当将 createElementNS 与 encodeURIComponent 而不是 outerHTML 结合使用时,会包含 xmlns 属性。因此,encodeURIComponent 确实是解决方案的一部分,以及使用 createElementNS。
    • 次要注意:如果您不需要 appendChild( element ) return 值。然后转储所有这些语句并使用append,它需要多个参数(或传播一个数组)请参阅:developer.mozilla.org/en-US/docs/Web/API/ParentNode/append
    • @AdamSassano 实际上是它的 serializeToString,它保留了命名空间并替换了 outerHTML。 encodeURIComponent 替换了替换函数。
    猜你喜欢
    • 2011-08-25
    • 2012-03-27
    • 1970-01-01
    • 2012-02-19
    • 1970-01-01
    • 1970-01-01
    • 2020-11-21
    • 2014-05-24
    • 1970-01-01
    相关资源
    最近更新 更多