我找不到一个java库来做你想要的,所以我研究了一个SVG并修改它的样式,并将其转换为图像。对于这项任务,我首先想到的是:Apache Batik。
我选择使用维基媒体上提供的开源 svg 地图(类似于 Gregor Opheys 的答案),因为它不是这样做的,所以你不关心许可,它也已经准备好按国家/地区进行简单的 CSS 修改。(有关说明,请参阅 SVG 注释)。有一个问题,维基媒体上的一些图像是由python 脚本生成的,它将 CSS 样式也放在元素中。如果您想使用这些 SVG 文件之一,您必须处理它。
令我高兴的是,蜡染维基上几乎有一个完美的例子,只需要进行一些调整。我能够通过一个小的语法更改(他们的输出文件名为 .jpg 但它使用 png 转码器)和一个小的更改来生成一个修改后的图像 (png),以从项目资源而不是磁盘加载 svg。下面是我的小改动的示例代码:
public class MapMaker {
private final static String MAP_FLAT = "BlankMap-World6-Equirectangular.svg";
private final static String MAP_ROUND = "WorldMap.svg";
public static void main(String... args) {
try {
// make a Document with the base map
String parser = XMLResourceDescriptor.getXMLParserClassName();
SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser);
Document doc = f.createDocument("http://example.com/stuff",
MapMaker.class.getClassLoader().getResourceAsStream(MAP_ROUND));
// prepare to modify and transcode the document
SVGDocument sdoc = (SVGDocument) doc;
Element svgRoot = sdoc.getDocumentElement();
PNGTranscoder t = new PNGTranscoder();
TranscoderInput input = new TranscoderInput(doc);
// find the existing stylesheet in the document
NodeList stylesList = doc.getElementsByTagName("style");
Node styleNode = stylesList.item(0);
// append another stylesheet after the existing one
SVGStyleElement style = (SVGStyleElement) doc.createElementNS(SVG_NAMESPACE_URI, "style");
style.setAttributeNS(null, "type", "text/css");
style.appendChild(doc.createCDATASection(".us {fill: blue;}"));
styleNode.getParentNode().appendChild(style);
// transcode the map
OutputStream ostream = new FileOutputStream("outblue.jpg");
TranscoderOutput output = new TranscoderOutput(ostream);
t.transcode(input, output);
ostream.close();
// replace the appended stylesheet with another
SVGStyleElement oldStyle = style;
style = (SVGStyleElement) doc.createElementNS(SVG_NAMESPACE_URI, "style");
style.setAttributeNS(null, "type", "text/css");
style.appendChild(doc.createCDATASection(".us {fill: green;}"));
styleNode.getParentNode().replaceChild(style, oldStyle);
// transcode the revised map
File outFile = new File(System.getProperty("java.io.tmpdir"), "outgreen.png");
ostream = new FileOutputStream(outFile);
output = new TranscoderOutput(ostream);
t.transcode(input, output);
ostream.close();
System.out.println("Out File: " + outFile);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Run Code Online (Sandbox Code Playgroud)
正如我提到的,它的工作方式是在将其转换为您需要的光栅图像之前将 CSS 添加到 SVG。秘诀是SVGStyleElement,在这里你可以看到美国变绿了。对于任何其他国家/地区,您只需使用他们的 2 个字母的有向图并选择您想要填充的颜色。当然,因为它是 CSS,你也可以做一些事情,比如改变边框颜色或使用背景图像而不是颜色,所以你有很大的灵活性。
我确实不得不稍微处理一下依赖项,所以为了让你克服这个障碍,我将包括我的 maven 依赖项:
<dependencies>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-parser</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-css</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-svg-dom</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-transcoder</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-rasterizer</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-codec</artifactId>
<version>1.7</version>
</dependency>
</dependencies>
Run Code Online (Sandbox Code Playgroud)
如果您使用不同的构建管理器,请告诉我,我可以转储传递依赖树。
| 归档时间: |
|
| 查看次数: |
2418 次 |
| 最近记录: |