任何人都可以推荐一个Java组件,它可以让您创建漂亮的世界地图图像,突出显示某些国家/地区(基于某些统计信息)。与此图像类似的东西:
类似于谷歌地理图表(但对于Java):https://developers.google.com/chart/interactive/docs/gallery/geochart 但是在服务器端运行,没有互联网连接。理想情况下,我希望将权重加到一些国家,这些国家会按比例突出显示它们。
无论是开源还是商业(只要它不是价格荒谬的东西)。
答案 0 :(得分:4)
我无法找到一个java库来做你想要的东西,所以我研究了一个SVG并修改它的风格,并将其转换为图像。我首先想到了这个任务:Apache Batik。
我选择使用wikimedia上提供的开源svg地图(类似于Gregor Opheys的回答),因为它没有成功,所以你不关心许可,它也已经是现成的按国家/地区进行简单的CSS修改(有关说明,请参阅SVG注释)。有一个故障,维基媒体上的一些图像是由a python script生成的,它将CSS样式也放在元素中。如果您想使用其中一个SVG文件,则必须为此处理。
令我高兴的是,有almost a perfect example on the batik wiki,只需要几个调整。我能够通过一个小的语法更改(它们的outfile文件名为.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();
}
}
}
正如我所提到的,它的工作方式是在将SVG转换为您需要的光栅图像之前将其添加到SVG。秘密酱是SVGStyleElement
,在这里你可以看到美国变绿了。对于任何其他国家/地区,您只需使用他们的双字母有向图并选择您想要填充的颜色。当然,既然它是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>
如果你使用不同的构建管理器,请告诉我,我可以转储传递依赖树。
答案 1 :(得分:2)
看看GeoTools,它可能有你需要的东西。
答案 2 :(得分:2)
没有使用它并且不确定它是否适合您的需求,但您可以查看 Nasa WorldWind 。它具有SDK,似乎可以使用离线模式。
检查:
答案 3 :(得分:1)
好吧,你可以为此制作一个GWT应用程序。 GWT(Google Web ToolKit)是一个基于Java的应用程序制作平台。它提供了与您在Google Charts javascript API中看到的相同类型的可视化API,但是在java代码中。请查看基于Java的Chart API的此链接以及Java代码http://gwt-charts.appspot.com/#geochart中的地理图表的实例。希望这会有所帮助:)
答案 4 :(得分:1)
首先,您可以轻松地使用SVG世界地图滚动组件或更像自己的功能
(例如this)。
将java.util.Map
国家/地区名称保留为SVG源中给出的路径元素。
您的函数将采用一组国家/地区名称,并基本上将字符串的svg作为字符串返回。如果路径的id与集合中的id匹配,您将添加具有所需颜色的填充属性...
这是代码。您需要下载this并将其作为world.svg
放在同一文件夹中。然后传入您想要突出显示为参数的国家/地区。程序将编写一个文件out.svg
,您可以在浏览器中打开(我使用的是Firefox)。我希望它成功。我只是尝试从日食中运行它......
package com.examples.firstbundle;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.text.MessageFormat;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
public class SVGMap {
private static String prefix = "";
private static String postfix = "";
private static Map<String, String> worldMap = new TreeMap<String, String>();
private final static String pathFormat = "<path id=\"{0}\" d=\"{1}\" fill=\"{2}\" />";
static {
try {
List<String> lines = Files.readAllLines(FileSystems.getDefault().getPath("world.svg"), StandardCharsets.UTF_8);
boolean pathstarted = false;
for(String line : lines) {
if(isPath(line)) {
pathstarted = true;
worldMap.put(getCountry(line), getPath(line));
} else {
if(!pathstarted) {
prefix += line;
}
else {
postfix += line;
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
Set<String> countries = new TreeSet<String>();
for(String country : args) {
countries.add(country);
}
FileOutputStream fileOutputStream = new FileOutputStream("out.svg");
OutputStreamWriter out = new OutputStreamWriter(fileOutputStream, StandardCharsets.UTF_8);
out.append(prefix);
for(String country : worldMap.keySet()) {
out.append(MessageFormat.format(pathFormat, country, worldMap.get(country), countries.contains(country) ? "tomato" : "grey"));
}
out.append(postfix);
out.flush();
out.close();
}
private static String getPath(String line) {
String part = line.split("=")[2];
String path = part.split("\"")[1];
return path;
}
private static String getCountry(String line) {
String part = line.split("=")[1];
String country = part.split("\"")[1];
return country;
}
private static boolean isPath(String line) {
return line.startsWith("<path");
}
}
答案 5 :(得分:0)
我觉得你更好:
gvSIG以其用户友好的界面而闻名 访问最常见的格式,包括矢量和光栅格式。它 具有广泛的工具,可以与地理一样工作 信息(查询工具,布局创建,地理处理,网络, 等)