Мне необходимо встроить карты в моё оконное приложение на Java, не обязательно google-карты, мне нужно лишь находить место по заданным координатам, центрировать изображение на нём и далее рисовать маршрут (просто проводить линию, не как в google maps с учётом препятствий и т.д.) до новых координат и повторять цикл. Какую библиотеку лучше использовать для этого и какие методы в ней? Мой уровень знания Java начальный, до этого не работал со сторонними библиотеками.
Проще всего наверное использовать какую-нибудь Javascript библиотеку в JavaFX WebView (Java 8+). Например Leaflet как бесплатный вариант (FreeBSD лицензия). В этом примере создаётся карта и под ней кнопка "Test". Когда нажимаешь на кнопку то на карте медленно рисуется рандомный путь из десяти точек.
LeafletTest.javaimport javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import netscape.javascript.JSObject;
public class LeafletTest extends Application {
private WebEngine webEngine;
private Button testButton;
private boolean createdPath = false;
@Override
public void start(Stage primaryStage) throws Exception {
WebView webView = new WebView();
webView.setContextMenuEnabled(false);
webEngine = webView.getEngine();
webEngine.setJavaScriptEnabled(true);
webEngine.load(LeafletTest.class.getResource("map.html").toExternalForm());
JSObject window = (JSObject) webEngine.executeScript("window");
window.setMember("app", this);
testButton = new Button("Test");
testButton.setDisable(true);
StackPane browserPane = new StackPane(webView);
browserPane.setPrefSize(600, 400);
VBox pageContainer = new VBox(browserPane, testButton);
Scene scene = new Scene(pageContainer);
primaryStage.setScene(scene);
primaryStage.show();
}
public void mapIsReady() {
Platform.runLater(() -> {
testButton.setDisable(false); // button can be clicked now that the map is ready
testButton.setOnAction((e) -> { // what happens when the button is clicked
testButton.setDisable(true); //don't let button be clicked twice
new Thread(() -> { // thread to slowly draw random path
double randomLatitude = Math.random() * 45;
double randomLongitude = Math.random() * 90;
String polyLineName = "testPath";
if (createdPath) {
removePolyline(polyLineName); // remove old one if it exists
}
newPolyline(polyLineName);
createdPath = true;
for (int i = 0; i < 10; i++) {
centerMap(randomLatitude, randomLongitude, 6);
addPointToPolyline(polyLineName, randomLatitude, randomLongitude);
try {
Thread.sleep(2000); // wait 2 seconds between drawing points
} catch (InterruptedException e1) {
e1.printStackTrace();
}
randomLatitude += Math.random();
randomLongitude += Math.random();
}
Platform.runLater(() -> testButton.setDisable(false)); // now button can be clicked again
}).start();
});
});
}
private void centerMap(double lat, double lon, int zoom) {
Platform.runLater(
() -> webEngine.executeScript("theMap.setView(new L.LatLng(" + lat + ", " + lon + "), " + zoom + ");"));
}
private void newPolyline(String name) {
Platform.runLater(
() -> webEngine.executeScript("window." + name + " = L.polyline([], {color: 'red'}).addTo(theMap)"));
}
private void addPointToPolyline(String name, double lat, double lon) {
Platform.runLater(() -> webEngine
.executeScript("window." + name + ".addLatLng(new L.LatLng(" + lat + ", " + lon + "));"));
}
private void removePolyline(String name) {
Platform.runLater(() -> webEngine.executeScript("theMap.removeLayer(window." + name + ");"));
}
public static void main(String[] args) {
launch(args);
}
}
map.html
<!DOCTYPE html>
<html>
<head>
<title>Leaflet</title>
<meta charset="utf-8" />
<link rel="shortcut icon" type="image/x-icon" href="docs/images/favicon.ico" />
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.1/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.3.1/dist/leaflet.js" integrity="sha512-/Nsx9X4HebavoBvEBuyp3I7od5tA0UzAxs+j83KgC8PU0kgB4XiK4Lfe4y4cgBtaRJQEIFCW+oC506aPT2L1zw==" crossorigin=""></script>
</head>
<body style="margin:0; padding:0;">
<div id="mapid" style="width:600px; height:400px"></div>
<script>
theMap = L.map('mapid').setView([0, 0], 1);
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
maxZoom: 18,
attribution: 'Map data © <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, ' +
'<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
id: 'mapbox.streets'
}).addTo(theMap);
// call Java program to let it know that the page is done loading
app.mapIsReady();
</script>
</body>
</html>
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Какие существуют виды рекламных бордов и как выбрать подходящий?
Я хочу сделать анимацию для изменения цвета JComponent с любого на серый в течении 5 секунд/ I want to make an animation which would change JComponent's color from any color to grey and then back, but slowly,...
Даны две точки и середина между нимиПочему результат сравнения неверный? Изначально я использовал тип double, оказалось, что он не очень подходит...
Есть база данных, куда приходят данные о местоположение пользователя