Question

I want to keep the map center coordinates into some limits. For this I call the setCenter method inside my "center" related callback function:

map.addObserver("center", function (obj, key, newValue, oldValue) {

  var limits = {minLat: 47.4136, minLon: 5.9845, maxLat: 54.8073, maxLon: 14.3671};

  if (newValue.latitude < limits.minLat || newValue.longitude < limits.minLon || 
      newValue.latitude > limits.maxLat || newValue.longitude > limits.maxLon) {

      var newLatLon = {latitude:  Math.max(Math.min(newValue.latitude, limits.maxLat), limits.minLat),
                       longitude: Math.max(Math.min(newValue.longitude, limits.maxLon), limits.minLon)};

      map.setCenter(nokia.maps.geo.Coordinate.fromObject(newLatLon));

      console.log(newValue);
      console.log(map.center);
  }
});

If I drag the map outside the limits, I see in the console the map.center being correctly adjusted, but the newValue coordinates keep being outisde the limits.

Did I misunderstand the API ?

I am using http://api.maps.nokia.com/2.2.3/jsl.js?with=all

Was it helpful?

Solution

Adding an observer to a property and then altering that property within the observer function is not guaranteed to work for all properties. My understanding is that re-setting the center is not supported in order to avoid infinite loops. You would be better off using the event framework rather than observers in this case.

The code below restricts the centre of the map to remain within a rectangle centred on Germany. If you drag the map it will stop dead, if you flick the map it will bounce back. You will need to obtain your own free app id and token to get it to work.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=7; IE=EmulateIE9" />
        <title>Nokia Maps API Example: Restricted Area</title>
        <!-- KML support is required here. -->
        <script type="text/javascript" charset="UTF-8" src="http://api.maps.nokia.com/2.2.3/jsl.js"></script>


</head>


<style type="text/css">
            html {
                overflow:hidden;
            }

            body {
                margin: 0;
                padding: 0;
                overflow: hidden;
                width: 100%;
                height: 100%;
                position: absolute;
            }

            #mapContainer {
                width: 80%;
                height: 80%;
            }
        </style>
    </head>
    <body>      
        <div id="mapContainer"></div>
        <script type="text/javascript">
/////////////////////////////////////////////////////////////////////////////////////
// Don't forget to set your API credentials
//
// Replace with your appId and token which you can obtain when you 
// register on http://api.developer.nokia.com/ 
//
            nokia.Settings.set( "appId", "APP ID"); 
            nokia.Settings.set( "authenticationToken", "TOKEN");
//          
/////////////////////////////////////////////////////////////////////////////////////   
        </script>
        <div id="uiContainer"></div>
        <script>

var mapContainer = document.getElementById("mapContainer");
var map = new nokia.maps.map.Display(mapContainer, {
    center: [51, 7],
    zoomLevel: 6
    });

map.addComponent(new nokia.maps.map.component.Behavior());  
var dragger = map.getComponentById("panning.Drag");    


// Set of initial geo coordinates to create the purple polyline
var points = [
        new nokia.maps.geo.Coordinate(47.4136, 5.9845),
        new nokia.maps.geo.Coordinate(47.4136, 14.3671),
        new nokia.maps.geo.Coordinate(54.8073, 14.3671),
        new nokia.maps.geo.Coordinate(54.8073, 5.9845),
        new nokia.maps.geo.Coordinate(47.4136, 5.9845)
    ];

// Transparent purple polyline
map.objects.add(new nokia.maps.map.Polyline(
    points,
    {   
        pen: {
            strokeColor: "#22CA", 
            lineWidth: 5
        }
    }
)); 



var restrict = function(evt) {   

     var limits = {minLat: 47.4136, minLon: 5.9845, maxLat: 54.8073, maxLon: 14.3671};

  if (map.center.latitude < limits.minLat || map.center.longitude < limits.minLon || 
      map.center.latitude > limits.maxLat || map.center.longitude > limits.maxLon) {

      var latitude =  Math.max(Math.min(map.center.latitude, limits.maxLat), limits.minLat);
      var longitude = Math.max(Math.min(map.center.longitude, limits.maxLon), limits.minLon);    
      map.setCenter(new nokia.maps.geo.Coordinate(latitude,longitude));      
      evt.cancel();
  }
}


map.addListener("dragend", restrict);
map.addListener("drag", restrict);
map.addListener("mapviewchange", restrict);
map.addListener("mapviewchangeend", restrict);
map.addListener("mapviewchangestart", restrict);


 </script>
    </body>
</html>

I have added event listeners to five events here, dragend, drag, mapviewchange, mapviewchangeend and mapviewchangestart - depending upon the effect you require, you may not need them all. The line evt.cancel(); stops the event from being processed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top