【JAVAFX 构建中国地图2021最新版】
-
一直在想中国地图如何能够在界面中实现,查找资料后发现地图的轮廓原来是一堆节点构成.于是中国地图它来了.
-
中国地图数据来源:http://datav.aliyun.com/tools/atlas/index.html
-
版本:V3
-
地图数据版本数据更新于2021.5
-
地图构建效果:
-
版本1.0
-
版本2.0
-
中国地图数据绘制实现
地图数据默认绘制的节点是反向的,需要修正处理,同时内蒙古自治区的数据和其他省份的数据在构建格式上有不同.如有其他问题可以留言交流.
package com.liangchao.modelcenter.uisystem.controller.tool;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.liangchao.modelcenter.uisystem.frame.App;
import com.liangchao.modelcenter.utils.ColorUtil;
import com.liangchao.modelcenter.utils.FileUtil;
import com.liangchao.modelcenter.utils.javafx.MouseMove;
import com.liangchao.modelcenter.utils.javafx.SupperController;
import de.felixroske.jfxsupport.FXMLController;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.paint.Color;
import javafx.scene.shape.Polygon;
import lombok.*;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* 中国地图图形绘制
*/
@FXMLController
public class ChineseMapUIController extends SupperController {
@FXML
private Label name;
@FXML
private Label code;
@FXML
private Label level;
@FXML
private VBox infoBox;//信息
@FXML
private AnchorPane canvas;//绘制面板
@Autowired
private ObjectMapper objectMapper;
private MediaPlayer mediaPlayer;
private static boolean play = false;
private List<Polygon> polygonList;
private Polygon thisPolygon;
private static final String SELECT_POLYGON = "select-polygon";
@Override
public void closeHandle() {
if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer = null;
}
play = false;
}
@Override
public void openHandle(Object... param) {
try {
this.drawChineseMap();
} catch (Exception e) {
e.printStackTrace();
}
//绑定属性面板拖动
infoBox.setLayoutX(10);
infoBox.setLayoutY(10);
new MouseMove(infoBox).bind();
this.name.setText("");
this.code.setText("");
this.level.setText("");
}
/**
* 绘制地图
*/
private void drawChineseMap() throws Exception {
Map map;
List list, list1, list2;
polygonList = new LinkedList<>();
double scale = 12, w = App.controller().getWinWidth() / 2, w0 = 550, h = App.controller().getWinHeight() / 2;
h = 670;
for (Object object : loadMap()) {
map = (Map) ((Map) object).get("properties");
// 各块轮廓
list = (List) ((Map) ((Map) object).get("geometry")).get("coordinates");
for (Object root : list) {
// 轮廓节点
Polygon polygon = new Polygon();
polygonList.add(polygon);
Entity entity = new Entity();
entity.setPolygon(polygon);
entity.setName(map.get("name").toString());
entity.setAdcode(map.get("adcode").toString());
list2 = (List) map.get("center");
if (list2 != null) {
entity.setCenterX((Double) list2.get(0));
entity.setCenterY((Double) list2.get(1));
}
list2 = (List) map.get("centroid");
if (list2 != null) {
entity.setCentroidX((Double) list2.get(0));
entity.setCentroidY((Double) list2.get(1));
}
entity.setChildrenNum((Integer) map.get("childrenNum"));
entity.setLevel(map.get("level") != null ? map.get("level").toString() : null);
entity.setParentCode(map.get("parent") != null ? (Integer) ((Map) map.get("parent")).get("adcode") : null);
entity.setSubFeatureIndex((Integer) map.get("subFeatureIndex"));
list2 = (List) map.get("acroutes");
if (list2 != null) {
entity.setAcroutes((Integer) list2.get(0));
}
polygon.getStyleClass().add("polygon");
polygon.setFill(Color.web(ColorUtil.toHex(), 0.95));
polygon.setOnMouseClicked(event -> {
this.name.setText(entity.getName());
this.code.setText(entity.getAdcode());
this.level.setText(this.convertLevel(entity.getLevel()));
});
list1 = (List) root;
list = (List) list1.get(0);
// 内蒙古自治区 数据在上一级list中 比较特殊
if (entity.getName().equals("内蒙古自治区")) {
list = list1;
}
int i = 0;
for (Object ls : list) {
if (ls instanceof ArrayList) {
int j = 0;
for (Object val : (List) ls) {
polygon.getPoints().add(j % 2 != 0 ? h - (Double) val * scale : (Double) val * scale - w0);
j++;
}
} else {
System.out.println(ls.getClass().getName() + " other ");
}
i++;
}
canvas.getChildren().add(polygon);
}
}
}
public List loadMap() throws Exception {
// https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json
// http://datav.aliyun.com/tools/atlas/index.html
//
// 数据来源于高德开放平台,数据更新于2020.4
String file = this.getClass().getResource("/chinese_full.json").getFile();
// 获取第一级数据
return (List) objectMapper.readValue(FileUtil.file(file), Map.class).get("features");
}
/**
* level 转换
*/
private String convertLevel(String level) {
// country:国家
// province:省份(直辖市会在province和city显示)
// city:市(直辖市会在province和city显示)
// district:区县
// street:街道
String v = null;
if (level == null) {
return v;
}
switch (level) {
case "country":
v = "国家";
break;
case "province":
v = "省份";
break;
case "city":
v = "市";
break;
case "district":
v = "区县";
break;
case "street":
v = "街道";
break;
}
return v;
}
/**
* 播放音乐
*/
public void playMusicAction(MouseEvent event) {
if (play) {
mediaPlayer.stop();
play = false;
return;
}
Media media2 = new Media(this.getClass().getResource("/audio/chinese.mp3").toString());
mediaPlayer = new MediaPlayer(media2);
mediaPlayer.setAudioSpectrumListener((timestamp, duration, magnitudes, phases) -> {
});
mediaPlayer.onStoppedProperty().addListener((observable, oldValue, newValue) -> {
play = false;
});
play = true;
mediaPlayer.play();
}
/**
* 节点数据信息
*/
@Setter
@Getter
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class Entity {
private String name;//名称
private String adcode;//编码
private Double centerX;//中心X
private Double centerY;//中心y
private Double centroidX;//面心 x
private Double centroidY;//面心 y
private Integer childrenNum; //子节点数量
private String level;//级别
private Integer parentCode; //父编码
private Integer subFeatureIndex;//子功能索引
private Integer acroutes;
private Polygon polygon;//节点
}
}
- 如有问题留言交流.