gluonhq / maps

https://gluonhq.com/labs/maps/
GNU General Public License v3.0
141 stars 35 forks source link

Add zoom level support to flyTo() method #43

Open dlemmermann opened 4 years ago

dlemmermann commented 4 years ago

It would be nice if we could not only fly to a location but at the same time to a given zoom level.

abhinayagarwal commented 4 years ago

@dlemmermann This is a good idea. Would you be willing to add this support?

abhinayagarwal commented 3 years ago

I have tried to implement this, however, the zooming can lead to glitches and bad UX. I personally feel like we should first fix https://github.com/gluonhq/maps/issues/22

Here is the patch from my changes:

diff --git a/maps/src/main/java/com/gluonhq/impl/maps/BaseMap.java b/maps/src/main/java/com/gluonhq/impl/maps/BaseMap.java
index 79125d4..abf798e 100644
--- a/maps/src/main/java/com/gluonhq/impl/maps/BaseMap.java
+++ b/maps/src/main/java/com/gluonhq/impl/maps/BaseMap.java
@@ -320,6 +320,10 @@ public class BaseMap extends Group {
     public DoubleProperty prefCenterLat() {
         return prefCenterLat;
     }
+
+    public DoubleProperty getPrefZoom() {
+        return prefZoom;
+    }

     private final void loadTiles() {
         logger.fine("[JVDBG] loadTiles");
diff --git a/maps/src/main/java/com/gluonhq/maps/MapView.java b/maps/src/main/java/com/gluonhq/maps/MapView.java
index 705117f..5a063c6 100644
--- a/maps/src/main/java/com/gluonhq/maps/MapView.java
+++ b/maps/src/main/java/com/gluonhq/maps/MapView.java
@@ -220,6 +220,25 @@ public class MapView extends Region {
         );
         timeline.play();
     }
+    
+    public void flyTo(double waitTime, MapPoint mapPoint, double zoom, double seconds) {
+        if ((timeline != null) && (timeline.getStatus() == Status.RUNNING)) {
+            timeline.stop();
+        }
+        double currentLat = baseMap.centerLat().get();
+        double currentLon = baseMap.centerLon().get();
+        double currentZoom = baseMap.zoom().getValue();
+
+        timeline = new Timeline(
+            new KeyFrame(Duration.ZERO, new KeyValue(baseMap.prefCenterLat(), currentLat), new KeyValue(baseMap.prefCenterLon(), currentLon), new KeyValue(baseMap.getPrefZoom(), currentZoom)),
+            new KeyFrame(Duration.seconds(waitTime), new KeyValue(baseMap.prefCenterLat(), currentLat), new KeyValue(baseMap.prefCenterLon(), currentLon), new KeyValue(baseMap.getPrefZoom(), currentZoom)),
+            new KeyFrame(Duration.seconds(waitTime + seconds), 
+                    new KeyValue(baseMap.prefCenterLat(), mapPoint.getLatitude()),
+                    new KeyValue(baseMap.prefCenterLon(), mapPoint.getLongitude(), Interpolator.EASE_BOTH),
+                    new KeyValue(baseMap.getPrefZoom(), zoom, Interpolator.EASE_BOTH))
+        );
+        timeline.play();
+    }

     /**
      * Set a supplier of an Image that can be used as placeholder by the Tile