Help about ZoomControls

3376
12
09-02-2019 05:49 AM
S_MMaruf
New Contributor II

Hi , 

I am trying to develop zooControls like zoomIn and zoomOut.  i give below the code about zoomIn and ZoomOut.

public void zoomIn() {
double x, y;
x= mapView.getScaleX();
y= mapView.getScaleY();
mapView.setScaleX(x+1);
mapView.setScaleY(y+1);

}

public void zoomOut() {
double x, y;

x= mapView.getScaleX();
y= mapView.getScaleY();
mapView.setScaleX(x-1);
mapView.setScaleY(y-1);
}

but the problem is when i click zoomIn button the mapview is overlaping with other pane and when i click zoomOut , it is not working and mapview is not zoomout within its stackpane like mouse's zoomIn and zoomout. i attach some code snippet.

For my  map application, changes zoom level of map by +1 or -1 and default minimum zoom level is 0, default maximum zoom level is 18.

so , there is another way to work with directly with mapview's zoom level?? above code is not working like mouse's zooming. can you guys give recommendation how to solve this problem?

Tags (1)
12 Replies
ColinAnderson1
Esri Contributor

Hi,

The methods that you are trying to to use on the MapView refer to JavaFX scaling - literally scaling the size of the control.

You can zoom the map by changing the ViewPoint as shown below.

Button zoomIn = new Button("Zoom in");
Button zoomOut = new Button("Zoom out");

zoomIn.setOnAction(a -> {
  Viewpoint current = mapView.getCurrentViewpoint(Viewpoint.Type.CENTER_AND_SCALE);
  Viewpoint zoomedIn = new Viewpoint((Point) current.getTargetGeometry(), current.getTargetScale() / 2.0);
  mapView.setViewpointAsync(zoomedIn);
});

zoomOut.setOnAction(a -> {
  Viewpoint current = mapView.getCurrentViewpoint(Viewpoint.Type.CENTER_AND_SCALE);  
  Viewpoint zoomedOut = new Viewpoint((Point) current.getTargetGeometry(), current.getTargetScale() * 2.0);
  mapView.setViewpointAsync(zoomedOut);
});

S_MMaruf
New Contributor II

Hi,

your hint is nicely working. but how can i implement that zoomlevel max 18 and zoomlevel min 0?

0 Kudos
ColinAnderson1
Esri Contributor

You can access the scale for each LOD something like

var tiledLayer = new ArcGISTiledLayer("http://services.arcgisonline.com/arcgis/rest/services/World_Topo_Map/MapServer");
tiledLayer.addDoneLoadingListener(() -> {
  var lods = tiledLayer.getTileInfo().getLevelsOfDetail();
  lods.forEach(lod -> System.out.println(lod.getScale()));
});

and use the scale in the zoom in/zoom out buttons.

0 Kudos
S_MMaruf
New Contributor II

Hello,

thank you for the helpful reply . i am still facing confusion that for zoom control . i explain now little bit why i need zoom level , for map application max zoom level will be 18 and  when zoom level going 18 or 18 plus the zoomln button will be disable .for also zoomOut when zoomlevel 0 (min) will be reached then zoomOut button will be disable . for those i need to work with some how zoomlevel 18 and 0 for respective max and min and disable those two button on those two zoomlevel respectively. i am using Wmslayer Class in my map application.

//zoomIn Button

public void zoomIn(ActionEvent event) {

map.zoomControl(true) ;

}
//zoomOut Button
public void zoomOut(ActionEvent event) {

map.zoomControl(false);

}

//zoomControl method

public void zoomControl(boolean zoom) {

if(zoom == true) {
Viewpoint current = mapView.getCurrentViewpoint(Viewpoint.Type.CENTER_AND_SCALE);
Viewpoint zoomedIn = new Viewpoint((Point) current.getTargetGeometry(),
current.getTargetScale() / 2.0);
mapView.setViewpointAsync(zoomedIn);


}else {

Viewpoint current = mapView.getCurrentViewpoint(Viewpoint.Type.CENTER_AND_SCALE);
Viewpoint zoomedOut = new Viewpoint((Point) current.getTargetGeometry(),
current.getTargetScale() * 2.0);
mapView.setViewpointAsync(zoomedOut);

}

}

0 Kudos
ColinAnderson1
Esri Contributor

I think you can do this by setting the min and max scales the the appropriate levels of detail e.g.

tiledLayer.setMinScale(lods.get(0).getScale());

tiledLayer.setMaxScale(lods.get(18).getScale());

0 Kudos
S_MMaruf
New Contributor II

Hi,

I implement your idea . but it doesnt disable the button. can you help me to sort out where i am doing wrong  ??

//zoomIn Button

public void zoomIn(ActionEvent event) {

map.zoomControl(true) ;

}
//zoomOut Button 
public void zoomOut(ActionEvent event) {

map.zoomControl(false);

}

//zoomControl method

public void zoomControl(boolean zoom) {

var lods = tiledLayer.getTileInfo().getLevelsOfDetail();
tiledLayer.setMaxScale(lods.get(18).getScale());
tiledLayer.setMinScale(lods.get(0).getScale());
if(zoom == true) {

Viewpoint current = mapView.getCurrentViewpoint(Viewpoint.Type.CENTER_AND_SCALE);
Viewpoint zoomedIn = new Viewpoint((Point) current.getTargetGeometry(),
current.getTargetScale() / 2.0);
mapView.setViewpointAsync(zoomedIn);


if (this.equals(tiledLayer.getMaxScale())) {

zoomIn.setDisable(true);
}
}

else {

Viewpoint current = mapView.getCurrentViewpoint(Viewpoint.Type.CENTER_AND_SCALE);
Viewpoint zoomedOut = new Viewpoint((Point) current.getTargetGeometry(),
current.getTargetScale() * 2.0);
mapView.setViewpointAsync(zoomedOut);

if (this.equals(tiledLayer.getMinScale())) {
zoomIn.setDisable(true);

}

}

}

0 Kudos
ColinAnderson1
Esri Contributor

mapView.setViewpointAsync(zoomedIn) is an async call so you would have to add a done listener if you want to take action when the new scale is reached since it doesn’t happen immediately so something like

mapView.setViewpointAsync(zoomedIn).addDoneListener(() -> {

// check to see if zoom in or zoom out should be disabled/enabled

});

An alternative would be to add a listener for scale changes on the MapView. As an example the following would disable the zoom in when you reach LOD 18 but otherwise enable the button.

mapView.addMapScaleChangedListener(s -> zoomIn.setDisable(mapView.getMapScale() <= lods.get(18).getScale()));

0 Kudos
S_MMaruf
New Contributor II

i used your alternative apporach . but i get exception

public void zoomControl(boolean zoom) {

var lods = tiledLayer.getTileInfo().getLevelsOfDetail();
tiledLayer.setMaxScale(lods.get(18).getScale());
tiledLayer.setMinScale(lods.get(0).getScale());
double MaxZoomLevel = tiledLayer.getMaxScale();
double MinZoomLevel = tiledLayer.getMinScale();

//zoomIn.setDisable(false);
//zoomOut.setDisable(false);


if(zoom == true) {

Viewpoint current = mapView.getCurrentViewpoint(Viewpoint.Type.CENTER_AND_SCALE);
Viewpoint zoomedIn = new Viewpoint((Point) current.getTargetGeometry(),
current.getTargetScale() / 2.0);

mapView.setViewpointAsync(zoomedIn);
mapView.addMapScaleChangedListener(s -> zoomIn.setDisable(mapView.getMapScale() <= lods.get(18).getScale()));


}

else {

Viewpoint current = mapView.getCurrentViewpoint(Viewpoint.Type.CENTER_AND_SCALE);
Viewpoint zoomedOut = new Viewpoint((Point) current.getTargetGeometry(),
current.getTargetScale() * 2.0);

mapView.setViewpointAsync(zoomedOut);

mapView.addMapScaleChangedListener(s -> zoomOut.setDisable(mapView.getMapScale() >= lods.get(0).getScale()));

}
}

==============================================================================

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at iJMSFx/application.IJMSMap.lambda$1(IJMSMap.java:166)
at com.esri.arcgisruntime/com.esri.arcgisruntime.internal.mapping.view.MapScaleChangedListenerRunnerImpl.run(MapScaleChangedListenerRunnerImpl.java:51)
at com.esri.arcgisruntime/com.esri.arcgisruntime.internal.mapping.view.MapViewImpl$2.scaleChanged(MapViewImpl.java:101)
at com.esri.arcgisruntime/com.esri.arcgisruntime.internal.jni.CoreMapView.onScaleChanged(CoreMapView.java:366)
at com.esri.arcgisruntime/com.esri.arcgisruntime.internal.mapping.view.RenderingContext.nativePulse(Native Method)
at com.esri.arcgisruntime/com.esri.arcgisruntime.internal.mapping.view.RenderingContext.pulse(RenderingContext.java:97)
at java.base/java.util.concurrent.CopyOnWriteArrayList.forEach(CopyOnWriteArrayList.java:803)
at com.esri.arcgisruntime/com.esri.arcgisruntime.internal.mapping.view.PulseThread$1.handle(PulseThread.java:31)
at javafx.graphics/javafx.animation.AnimationTimer$AnimationTimerReceiver.lambda$handle$0(AnimationTimer.java:57)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:389)
at javafx.graphics/javafx.animation.AnimationTimer$AnimationTimerReceiver.handle(AnimationTimer.java:56)
at javafx.graphics/com.sun.scenario.animation.AbstractMasterTimer.timePulseImpl(AbstractMasterTimer.java:357)
at javafx.graphics/com.sun.scenario.animation.AbstractMasterTimer$MainLoop.run(AbstractMasterTimer.java:267)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:515)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:499)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulseFromQueue(QuantumToolkit.java:492)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$11(QuantumToolkit.java:320)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
at java.base/java.lang.Thread.run(Thread.java:835)
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at iJMSFx/application.IJMSMap.lambda$1(IJMSMap.java:166)
at com.esri.arcgisruntime/com.esri.arcgisruntime.internal.mapping.view.MapScaleChangedListenerRunnerImpl.run(MapScaleChangedListenerRunnerImpl.java:51)
at com.esri.arcgisruntime/com.esri.arcgisruntime.internal.mapping.view.MapViewImpl$2.scaleChanged(MapViewImpl.java:101)
at com.esri.arcgisruntime/com.esri.arcgisruntime.internal.jni.CoreMapView.onScaleChanged(CoreMapView.java:366)
at com.esri.arcgisruntime/com.esri.arcgisruntime.internal.mapping.view.RenderingContext.nativePulse(Native Method)
at com.esri.arcgisruntime/com.esri.arcgisruntime.internal.mapping.view.RenderingContext.pulse(RenderingContext.java:97)
at java.base/java.util.concurrent.CopyOnWriteArrayList.forEach(CopyOnWriteArrayList.java:803)
at com.esri.arcgisruntime/com.esri.arcgisruntime.internal.mapping.view.PulseThread$1.handle(PulseThread.java:31)
at javafx.graphics/javafx.animation.AnimationTimer$AnimationTimerReceiver.lambda$handle$0(AnimationTimer.java:57)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:389)
at javafx.graphics/javafx.animation.AnimationTimer$AnimationTimerReceiver.handle(AnimationTimer.java:56)
at javafx.graphics/com.sun.scenario.animation.AbstractMasterTimer.timePulseImpl(AbstractMasterTimer.java:357)
at javafx.graphics/com.sun.scenario.animation.AbstractMasterTimer$MainLoop.run(AbstractMasterTimer.java:267)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:515)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:499)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulseFromQueue(QuantumToolkit.java:492)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$11(QuantumToolkit.java:320)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
at java.base/java.lang.Thread.run(Thread.java:835)
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at iJMSFx/application.IJMSMap.lambda$1(IJMSMap.java:166)
at com.esri.arcgisruntime/com.esri.arcgisruntime.internal.mapping.view.MapScaleChangedListenerRunnerImpl.run(MapScaleChangedListenerRunnerImpl.java:51)
at com.esri.arcgisruntime/com.esri.arcgisruntime.internal.mapping.view.MapViewImpl$2.scaleChanged(MapViewImpl.java:101)
at com.esri.arcgisruntime/com.esri.arcgisruntime.internal.jni.CoreMapView.onScaleChanged(CoreMapView.java:366)
at com.esri.arcgisruntime/com.esri.arcgisruntime.internal.mapping.view.RenderingContext.nativePulse(Native Method)
at com.esri.arcgisruntime/com.esri.arcgisruntime.internal.mapping.view.RenderingContext.pulse(RenderingContext.java:97)
at java.base/java.util.concurrent.CopyOnWriteArrayList.forEach(CopyOnWriteArrayList.java:803)
at com.esri.arcgisruntime/com.esri.arcgisruntime.internal.mapping.view.PulseThread$1.handle(PulseThread.java:31)
at javafx.graphics/javafx.animation.AnimationTimer$AnimationTimerReceiver.lambda$handle$0(AnimationTimer.java:57)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:389)
at javafx.graphics/javafx.animation.AnimationTimer$AnimationTimerReceiver.handle(AnimationTimer.java:56)
at javafx.graphics/com.sun.scenario.animation.AbstractMasterTimer.timePulseImpl(AbstractMasterTimer.java:357)
at javafx.graphics/com.sun.scenario.animation.AbstractMasterTimer$MainLoop.run(AbstractMasterTimer.java:267)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:515)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:499)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulseFromQueue(QuantumToolkit.java:492)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$11(QuantumToolkit.java:320)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
at java.base/java.lang.Thread.run(Thread.java:835)

0 Kudos
ColinAnderson1
Esri Contributor

I think maybe you are adding the MapView scale listener in the wrong place. Try something like this which should disable the zoom in once you reach LOD 18 and enable it if you zoom back out…

import com.esri.arcgisruntime.geometry.Point;

import com.esri.arcgisruntime.layers.ArcGISTiledLayer;

import com.esri.arcgisruntime.mapping.ArcGISMap;

import com.esri.arcgisruntime.mapping.Basemap;

import com.esri.arcgisruntime.mapping.Viewpoint;

import com.esri.arcgisruntime.mapping.view.MapView;

import javafx.application.Application;

import javafx.application.Platform;

import javafx.scene.Scene;

import javafx.scene.control.Button;

import javafx.scene.layout.BorderPane;

import javafx.scene.layout.HBox;

import javafx.stage.Stage;

public class App extends Application {

MapView mapView = new MapView();

@Override

public void start(Stage stage) throws Exception {

Platform.setImplicitExit(true);

var borderPane = new BorderPane();

var scene = new Scene(borderPane);

stage.setScene(scene);

stage.setWidth(500);

stage.setHeight(500);

stage.show();

var map = new ArcGISMap();

var tiledLayer = new ArcGISTiledLayer("http://services.arcgisonline.com/arcgis/rest/services/World_Topo_Map/MapServer");;

tiledLayer.addDoneLoadingListener(() -> {

var lods = tiledLayer.getTileInfo().getLevelsOfDetail();

lods.forEach(lod -> System.out.println(lod.getLevel() + " " + lod.getScale() + " " + lod.getResolution()));

//tiledLayer.setMinScale(lods.get(0).getScale());

//tiledLayer.setMaxScale(lods.get(18).getScale());

HBox box = new HBox();

borderPane.setBottom(box);

Button zoomIn = new Button("Zoom in");

Button zoomOut = new Button("Zoom out");

zoomIn.setOnAction(a -> {

Viewpoint current = mapView.getCurrentViewpoint(Viewpoint.Type.CENTER_AND_SCALE);

Viewpoint zoomedIn = new Viewpoint((Point) current.getTargetGeometry(), current.getTargetScale() / 2.0);

});

zoomOut.setOnAction(a -> {

Viewpoint current = mapView.getCurrentViewpoint(Viewpoint.Type.CENTER_AND_SCALE);

Viewpoint zoomedOut = new Viewpoint((Point) current.getTargetGeometry(), current.getTargetScale() * 2.0);

mapView.setViewpointAsync(zoomedOut);

});

box.getChildren().addAll(zoomIn, zoomOut);

mapView.addMapScaleChangedListener(s -> zoomIn.setDisable(mapView.getMapScale() <= lods.get(18).getScale()));

});

Basemap basemap = new Basemap();

basemap.getBaseLayers().add(tiledLayer);

map.setBasemap(basemap);

mapView.setMap(map);

borderPane.setCenter(mapView);

}

@Override

public void stop() throws Exception {

if (mapView != null) {

mapView.dispose();

}

}

public static void main(String[] args) {

launch(args);

}

}

0 Kudos