1

I have a simple map setup and I've been reading the documentation to find out how to set the center and zoom at the current geo location. I initialize my map's view to center at [0, 0] with zoom of 2, but I don't know which event to hook up the following code to center and zoom:

var coordinates = geolocation.getPosition();
positionFeature.setGeometry(coordinates ?
    new ol.geom.Point(coordinates) : null);
map.setView(new ol.View({
  center: geolocation.getPosition(),
  zoom: 15

I tried many on and once events for my Map and GeoLocation objects, but it seems that the location has yet to be properly set before these events are fired. Or they continually fire which calls the zoom and center functionality constantly.

The map works perfectly as is minus this issue. Is there an event that will fire after the entire map is loaded including the geo location?

I've added the code below for more clarity:

<html>
  <head>
    <title>Accessible Map</title>
    <link rel="stylesheet" href="https://openlayers.org/en/v4.2.0/css/ol.css" type="text/css">
    <!-- The line below is only needed for old environments like Internet Explorer and Android 4.x -->
    <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script>
    <script src="https://openlayers.org/en/v4.2.0/build/ol.js"></script>
    <style>
      a.skiplink {
        position: absolute;
        clip: rect(1px, 1px, 1px, 1px);
        padding: 0;
        border: 0;
        height: 1px;
        width: 1px;
        overflow: hidden;
      }
      a.skiplink:focus {
        clip: auto;
        height: auto;
        width: auto;
        background-color: #fff;
        padding: 0.3em;
      }
      #map:focus {
        outline: #4A74A8 solid 0.15em;
      }
    </style>
  </head>
  <body>
    <a class="skiplink" href="#map">Go to map</a>
    <div id="map" class="map" tabindex="0"></div>
    <script>
      // Heatmap data
      var vector = new ol.layer.Heatmap({
        source: new ol.source.Vector({
          url: 'https://openlayers.org/en/v4.2.0/examples/data/kml/2012_Earthquakes_Mag5.kml',
          format: new ol.format.KML({
            extractStyles: false
          })
        }),
        blur: parseInt(15, 10),
        radius: parseInt(5, 10)
      });

      vector.getSource().on('addfeature', function(event) {
        // 2012_Earthquakes_Mag5.kml stores the magnitude of each earthquake in a
        // standards-violating <magnitude> tag in each Placemark.  We extract it from
        // the Placemark's name instead.
        var name = event.feature.get('name');
        var magnitude = parseFloat(name.substr(2));
        event.feature.set('weight', magnitude - 5);
      });


      // Map
      var map = new ol.Map({
        layers: [
          new ol.layer.Tile({
            source: new ol.source.OSM()
          }),
          vector
        ],
        target: 'map',
        controls: ol.control.defaults({
          attributionOptions: /** @type {olx.control.AttributionOptions} */ ({
            collapsible: false
          })
        }),
        view: new ol.View({
          center: [0, 0],
          zoom: 2
        })
      });

      // Begin geolocation
      var geolocation = new ol.Geolocation({
        projection: map.getView().getProjection(),
        tracking: true,
        trackingOptions: {
          enableHighAccuracy: true,
          maximumAge: 2000
        }
      });

      // handle geolocation error.
      geolocation.on('error', function(error) {
        var info = document.getElementById('info');
        info.innerHTML = error.message;
        info.style.display = '';
      });

      // When the coordinates update
      geolocation.on("change:position", function() {
        var coordinates = geolocation.getPosition();
        positionFeature.setGeometry(coordinates ?
            new ol.geom.Point(coordinates) : null);
      });

      // Detail the accuracy of the location
      var accuracyFeature = new ol.Feature();
      geolocation.on('change:accuracyGeometry', function() {
        accuracyFeature.setGeometry(geolocation.getAccuracyGeometry());
      });

      // Style of the location icon
      var positionFeature = new ol.Feature();
      positionFeature.setStyle(new ol.style.Style({
        image: new ol.style.Circle({
          radius: 6,
          fill: new ol.style.Fill({
            color: '#3399CC'
          }),
          stroke: new ol.style.Stroke({
            color: '#fff',
            width: 2
          })
        })
      }));

      // Layout map
      new ol.layer.Vector({
        map: map,
        source: new ol.source.Vector({
          features: [accuracyFeature, positionFeature]
        })
      });

      // After rendering the map, center and zoom user's location
      map.once("change", function(){
        var coordinates = geolocation.getPosition();
        positionFeature.setGeometry(coordinates ?
            new ol.geom.Point(coordinates) : null);
        map.setView(new ol.View({
          center: geolocation.getPosition(),
          zoom: 15
        }));
      });
    </script>
  </body>
</html>
  • What is the geolocation object? Is this a map layer that you want to center the map over once it's finished loading? – rumski20 Jul 20 '17 at 13:49
  • The Geolocation object is here: openlayers.org/en/latest/apidoc/ol.Geolocation.html I want to center and zoom my map's view based on my geolocation's location once the location is available (i.e., once everything has finished loading). – Grant Bartel Jul 20 '17 at 13:57
  • I've included the original code in the question. – Grant Bartel Jul 20 '17 at 13:59
0

From this discussion, it seems there is no event when the map is "ready" (at least for openlayers3).

A solution is to add a map.setView() function to your geolocalisation layer:

  // Layout map
  var layer = new ol.layer.Vector({
    map: map,
    source: new ol.source.Vector({
      features: [accuracyFeature, positionFeature]
    })
  });

  layer.once("change", function(){
    map.setView(new ol.View({
      center: geolocation.getPosition(),
      zoom: 15
    }));
  });
  • I tried that actually. The problem is that whenever there's any change in the geolocation, that center and zoom functionality occurs, which is not what I need. I need to happen once at the beginning of the map's creation and only then, unless the user clicks some center button. – Grant Bartel Jul 20 '17 at 14:56
  • I tested the second code snippet and it works. Could you edit your answer to only include that? I'll then mark the answer correct. – Grant Bartel Jul 20 '17 at 15:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.