如何在Apache Batik中为SVG的currentColor指定自定义颜色值?
解决Apache Batik渲染SVG时currentColor默认黑色的问题
问题核心:currentColor的取值依赖于元素的color属性(沿DOM树继承),Batik在未指定该属性时会默认使用黑色。要自定义currentColor的值,只需给SVG根元素设置color属性即可,有两种实现方式:
方案1:直接修改SVG源文件
如果可以编辑SVG内容,直接在根<svg>标签中添加color属性,指定你需要的颜色值:
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" color="#2563eb" class="bi bi-clock" viewBox="0 0 16 16"> <path d="M8 3.5a.5.5 0 0 0-1 0V9a.5.5 0 0 0 .252.434l3.5 2a.5.5 0 0 0 .496-.868L8 8.71z" /> <path d="M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m7-8A7 7 0 1 1 1 8a7 7 0 0 1 14 0" /> </svg>
方案2:在转码前动态修改SVG DOM
如果无法修改原始SVG文件,可以在Batik转码前解析SVG为DOM对象,给根元素添加color属性,再进行转码。修改你的工具方法如下:
import org.w3c.dom.Document; import org.w3c.dom.Element; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; public static BufferedImage rasterize(InputStream svgInput, int width, int height, String currentColor) throws TranscoderException, Exception { AtomicReference<BufferedImage> results = new AtomicReference<BufferedImage>(); ImageTranscoder transcoder = new ImageTranscoder() { @Override public BufferedImage createImage(int width, int height) { return new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); } @Override public void writeImage(BufferedImage image, TranscoderOutput output) throws TranscoderException { results.set(image); } }; // 解析SVG为DOM并设置color属性 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); Document doc = factory.newDocumentBuilder().parse(svgInput); Element rootSvg = doc.getDocumentElement(); rootSvg.setAttribute("color", currentColor); // 将修改后的DOM转回InputStream ByteArrayOutputStream baos = new ByteArrayOutputStream(); Transformer transformer = TransformerFactory.newInstance().newTransformer(); transformer.transform(new DOMSource(doc), new StreamResult(baos)); InputStream modifiedSvgInput = new ByteArrayInputStream(baos.toByteArray()); // 原有转码逻辑 TranscodingHints hints = new TranscodingHints(); if (width > 0) hints.put(SVGAbstractTranscoder.KEY_WIDTH, (float) width); if (height > 0) hints.put(SVGAbstractTranscoder.KEY_HEIGHT, (float) height); hints.put(XMLAbstractTranscoder.KEY_DOM_IMPLEMENTATION, SVGDOMImplementation.getDOMImplementation()); hints.put(XMLAbstractTranscoder.KEY_DOCUMENT_ELEMENT_NAMESPACE_URI, SVGConstants.SVG_NAMESPACE_URI); hints.put(XMLAbstractTranscoder.KEY_DOCUMENT_ELEMENT, SVGConstants.SVG_SVG_TAG); hints.put(XMLAbstractTranscoder.KEY_XML_PARSER_VALIDATING, false); transcoder.setTranscodingHints(hints); transcoder.transcode(new TranscoderInput(modifiedSvgInput), null); return results.get(); }
调用时传入目标颜色值即可(支持十六进制、颜色名称等格式):
BufferedImage image = rasterize(svgInputStream, 100, 100, "#ff4500");
补充说明
currentColor本质是CSS变量,会继承元素的color属性值,给根SVG设置color后,所有使用currentColor的子元素都会继承这个颜色。- 如果需要更复杂的样式控制,也可以向DOM中插入内部CSS样式表(比如
<style>svg { color: #xxxxxx; }</style>),效果和直接设置属性一致。
内容的提问来源于stack exchange,提问作者Cardinal System
相关产品推荐
相关产品推荐

