繁体   English   中英

如何更改SVG颜色(在CSS中将SVG用作背景时)

[英]How to change SVG color (when using the SVG as background in CSS)

我正在努力通过css(svg作为背景CSS)更改svg对象的颜色。

我有这个

span {
    display:block;
    width: 12px;
    background: url('data:image/svg+xml;utf-8,<?xml version="1.0" encoding="utf-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" ><polygon points="6,4.5 0,0 0,1.208 6,5.708 12,1.208 12,0"/></svg>');
    height: 20px;
}

这可行,但是元素的颜色始终为黑色。 我想将其颜色更改为自定义颜色(例如蓝色)。 通过添加style="fill:#2C30FF" ,该元素将消失并且不显示任何内容,尽管如果svg元素包含在html中(而不是CSS背景),则此方法可以正常工作

有关示例,请参见小提琴。 应该显示3个元素,但不显示第二个元素,因为我添加了style="fill:#2C30FF"

的jsfiddle

为什么不起作用? 真的很感谢一些技巧。

#是URL中的保留字符,它指示片段标识符开头

您需要将#编码为%23

background: url('data:image/svg+xml;utf-8,<?xml version="1.0" encoding="utf-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" ><polygon points="6,4.5 0,0 0,1.208 6,5.708 12,1.208 12,0" style="fill:%232C30FF;"/></svg>');

更新的小提琴

我刚刚实现了Java解决方案,因此可以加载SVG文件并动态更改填充颜色。

这是我的代码-SvgImage.java

package com.svg.poc;

import org.apache.batik.anim.dom.SAXSVGDocumentFactory;
import org.apache.batik.anim.dom.SVGDOMImplementation;
import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.BridgeException;
import org.apache.batik.bridge.GVTBuilder;
import org.apache.batik.bridge.UserAgentAdapter;
import org.apache.batik.bridge.ViewBox;
import org.apache.batik.dom.util.DOMUtilities;
import org.apache.batik.ext.awt.image.GraphicsUtil;
import org.apache.batik.gvt.GraphicsNode;
import org.apache.batik.util.ParsedURL;
import org.apache.batik.util.XMLResourceDescriptor;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.svg.SVGDocument;
import org.w3c.dom.svg.SVGSVGElement;

import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;

public final class SvgImage {

    private GraphicsNode rootSvgNode;

    private SVGDocument svgDocument;

    public SvgImage(String imagePath) throws IOException {
        String parser = XMLResourceDescriptor.getXMLParserClassName();
        SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(parser);
        svgDocument = (SVGDocument) factory.createDocument(imagePath);
        rootSvgNode = getRootNode(svgDocument);
    }

    public SvgImage(SVGDocument document) {
        svgDocument = document;
        rootSvgNode = getRootNode(svgDocument);
    }


    private static GraphicsNode getRootNode(SVGDocument document) {
        UserAgentAdapter userAgentAdapter = new UserAgentAdapter();
        BridgeContext bridgeContext = new BridgeContext(userAgentAdapter);
        GVTBuilder builder = new GVTBuilder();
        return builder.build(bridgeContext, document);
    }


    public BufferedImage getImage(Integer heightOverride, Integer widthOverride) {

        int height = (heightOverride == null || heightOverride.intValue() == 0) ? fetchExistingImageHeightValue() : heightOverride;
        int width = (widthOverride == null || widthOverride.intValue() == 0) ? fetchExistingImageWidthValue() : widthOverride;

        BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = GraphicsUtil.createGraphics(bufferedImage);

        DOMImplementation impl = SVGDOMImplementation.getDOMImplementation();
        SVGDocument cloneDocument = (SVGDocument) DOMUtilities.deepCloneDocument(svgDocument, impl);
        SVGSVGElement root = cloneDocument.getRootElement();

        // @@TODO - Currently hardcoded the inbound new color for testing, will use the ReportConfiguration Colors soon.
        //String hardCodedHexColor = "#ff00ff"; // pink
        String hardCodedHexColor = "#008000"; // green
        updateTagFillColor(root.getElementsByTagName("rect"), hardCodedHexColor);
        updateTagFillColor(root.getElementsByTagName("path"), hardCodedHexColor);

        UserAgentAdapter userAgentAdapter = new UserAgentAdapter();
        BridgeContext ctx = new BridgeContext(userAgentAdapter);
        ctx.setDynamic(true);

        GVTBuilder builder = new GVTBuilder();
        GraphicsNode gvtRoot = builder.build(ctx, cloneDocument);

        AffineTransform px = new AffineTransform();

        String ref = new ParsedURL(svgDocument.getBaseURI()).getRef();
        try {
            px = ViewBox.getViewTransform(ref, root, width, height, ctx);
        } catch (BridgeException ex) {
            ex.printStackTrace();
        }

        g2d.transform(px);

        gvtRoot.paint(g2d);

        // Cleanup and return image
        g2d.dispose();
        return bufferedImage;
    }

    private void updateTagFillColor(NodeList nodeList, String newFillColor) {

        for (int i = 0; i < nodeList.getLength(); i++) {
            Node node = nodeList.item(i);
            NamedNodeMap namedNodeMap = node.getAttributes();
            for (int j = 0; j < namedNodeMap.getLength(); j++) {
                Node namedNode = namedNodeMap.item(j);
                if (namedNode.getNodeName().equalsIgnoreCase("fill")) {

                    StringBuilder beforeBuilder = new StringBuilder("\nBefore update: ")
                            .append("node name=" + namedNode.getNodeName())
                            .append(", node value=" + namedNode.getNodeValue());
                    System.out.println(beforeBuilder.toString());

                    namedNode.setNodeValue(newFillColor); // Change the color of the fill attribute.

                    StringBuilder afterBuilder = new StringBuilder("After update: ")
                            .append("node name=" + namedNode.getNodeName())
                            .append(", node value=" + namedNode.getNodeValue());
                    System.out.println(afterBuilder.toString());
                }
            }
        }
    }

    private int fetchExistingImageWidthValue() {
        return new Double(rootSvgNode.getBounds().getWidth()).intValue();
    }

    private int fetchExistingImageHeightValue() {
        return new Double(rootSvgNode.getBounds().getHeight()).intValue();
    }

}

实现:(称为此类-接口)

package com.svg.poc;

import java.awt.image.BufferedImage;

public interface SvgIconImageRenderer {

    BufferedImage getSvgImage(String svgImageFilePath);

    BufferedImage getSvgImage(String svgImageFilePath, Integer heightOverride, Integer widthOverride);

}

实现:(即此类-实现类)

package com.svg.poc;

import org.springframework.stereotype.Component;

import java.awt.image.BufferedImage;

@Component
public class SvgIconImageRendererImpl implements SvgIconImageRenderer {

    public BufferedImage getSvgImage(String svgImageFilePath) {
        return getSvgImage(svgImageFilePath, null, null);
    }

    public BufferedImage getSvgImage(String svgImageFilePath, Integer heightOverride, Integer widthOverride) {
        try {
            SvgImage svgImage = new SvgImage(getClass().getResource(svgImageFilePath).toURI().toString());
            return svgImage.getImage(heightOverride, widthOverride);
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

}

测试用例:

package com.svg.poc;

import org.apache.batik.swing.JSVGCanvas;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;

public class SVGImageLoaderTest {

    private SvgIconImageRenderer svgIconImageRenderer = new SvgIconImageRendererImpl();

    private static final String ICON_HOUSES_SVG_URL_PATH = "/icon-houses.svg";

    public static void main(String[] args) {
        JFrame f = new JFrame("Svg Image test");
        SVGImageLoaderTest app = new SVGImageLoaderTest(f);

        f.getContentPane().add(app.createComponents());
        f.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        f.setSize(400, 400);
        f.setVisible(true);
    }

    JFrame frame;
    JSVGCanvas svgCanvas = new JSVGCanvas();

    public SVGImageLoaderTest(JFrame f) {
        frame = f;
    }

    public JComponent createComponents() {
        BufferedImage bufferedSvgImage = svgIconImageRenderer.getSvgImage(ICON_HOUSES_SVG_URL_PATH);
        JLabel label = new JLabel(new ImageIcon(bufferedSvgImage));

        final JPanel panel = new JPanel(new BorderLayout());
        JPanel p = new JPanel(new FlowLayout(FlowLayout.LEFT));

        p.add(label);
        panel.add(p, BorderLayout.NORTH);
        panel.add(svgCanvas, BorderLayout.CENTER);

        return panel;
    }

}

图标houses.svg

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     width="300px" height="300px" viewBox="0 0 300 300" enable-background="new 0 0 300 300" xml:space="preserve">

    <g>

      <rect x="5" y="5" width="200" fill="#ff0000" height="30" rx="15" ry="15" stroke="gray" />

      <rect x="5" y="45" width="400" fill="#ff0000" height="30" rx="15" ry="15" stroke="gray" />

      <path display="inline" fill="#8D8379" d="M243.754,124.987c-31.017,0-56.246,25.249-56.246,56.257
        c0,28.494,45.661,106.85,50.86,115.676c1.128,1.911,3.173,3.08,5.386,3.08c2.212,0,4.27-1.169,5.395-3.08
        c5.208-8.826,50.862-87.182,50.862-115.676C300.011,150.236,274.771,124.987,243.754,124.987 M243.754,212.498
        c-17.241,0-31.255-14.015-31.255-31.254c0-17.229,14.014-31.256,31.255-31.256c17.24,0,31.254,14.026,31.254,31.256
        C275.008,198.483,260.995,212.498,243.754,212.498"/>

    </g>

    <polygon display="inline" fill="#8D8379" points="149.046,153.722 149.013,153.722 149.08,153.722     "/>

</svg>

Maven的依赖:

<dependencies>
        <!--svg image dependencies-->
        <dependency>
            <groupId>org.apache.xmlgraphics</groupId>
            <artifactId>batik-transcoder</artifactId>
            <version>1.8</version>
        </dependency>
        <dependency>
            <groupId>org.apache.xmlgraphics</groupId>
            <artifactId>batik-swing</artifactId>
            <version>1.8</version>
        </dependency>
        <dependency>
            <groupId>org.apache.xmlgraphics</groupId>
            <artifactId>xmlgraphics-commons</artifactId>
            <version>2.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.2.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>4.2.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.2.2.RELEASE</version>
        </dependency>
    </dependencies>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM