I'm struggling to change the color of an svg object via css (svg as background css).
I have this
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;
}
This works, but the color of the element is always black. I would like to change it color to a custom color (blue for example). By adding style="fill:#2C30FF"
, the element just disappears and shows nothing, although this work fine if the svg element is included in the html (not css background)
See the fiddle for an example. There should display 3 elements but the second doesn't show because I added style="fill:#2C30FF"
Why doesn't it work? Would really appreciate some tips.
# is a reserved character in URLs, it indicates the start of a fragment identifier .
You need to URL encode the # as %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>');
I have just implemented a java solution whereby I can load an SVG file and change the fill colors dynamically.
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();
}
}
Implementations: (That call this class - Interface)
package com.svg.poc;
import java.awt.image.BufferedImage;
public interface SvgIconImageRenderer {
BufferedImage getSvgImage(String svgImageFilePath);
BufferedImage getSvgImage(String svgImageFilePath, Integer heightOverride, Integer widthOverride);
}
Implementations: (That call this class - Implementation class)
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;
}
}
<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>
<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>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.