21

I have an OpenLayers 3 map with a base layer and a vector layer.

this.topoLayer = new ol.layer.Vector({
  source: new ol.source.Vector(),
  style: style
});

var baseLayer = new ol.layer.Tile({
    source: new ol.source.XYZ({
        url: 'http://[…]/{z}/{x}/{y}.png',
        crossOrigin: 'null'
    })
});

this.map = new ol.Map({
    target: 'map',
    layers: [baseLayer, this.topoLayer],
    view: new ol.View2D({
        center: ol.proj.transform([11.38,  48.54], this.options.markerEPSG, this.options.mapEPSG),
        zoom: 5,
    }),
});

Upon user interaction, I add and remove several features to the vector layer. Here is the function that adds a new feature:

  var feature = new ol.Feature({
        topo: topo,
        selected: false,
        geometry: new ol.geom.Point(ol.proj.transform(location, this.options.markerEPSG, this.options.mapEPSG)),
  });

  this.topoLayer.getSource().addFeatures([feature]);

After adding/removing a new feature I would like to automatically zoom and pan the map to fit my features. In the old OpenLayers API there was the getDataExtent function on vector layers to retrieve a "bounding box" around all features shown. But I wonder how to do this with the new API.

Christophe Roussy
  • 16,299
  • 4
  • 85
  • 85
SomeBdyElse
  • 427
  • 1
  • 4
  • 11
  • 1
    Right now, I store all active features in a separate array and calculate the extent from there. `var coordinates = features.map(function(feature) {return feature.getGeometry().getCoordinates();});` `var extent = ol.extent.boundingExtent(coordinates);` – SomeBdyElse Dec 28 '13 at 20:23
  • your solution in the comment works. One can call `map.getView().fit(extent, map.getSize())` to adjust the map. – philk Dec 08 '15 at 15:53

5 Answers5

31

In version 3.7, ol.View.fitExtent() and ol.View.fitGeometry() have been unified in a single function: fit.

So now the code is:

 var extent = myLayer.getSource().getExtent();
 map.getView().fit(extent, map.getSize());
Mister Smith
  • 27,417
  • 21
  • 110
  • 193
9

Based on Tyler DeWitt's answer you should be able to do something like this:

var view = yourmap.getView();
var view2D = view.getView2D();
var extent = yourlayer.getSource().getExtent();

view2D.fitExtent(extent, yourmap.getSize());

Edit: Like Tim and Stuart said the above doesn't work anymore. The following should do the trick instead:

 var extent = yourlayer.getSource().getExtent();
 map.getView().fitExtent(extent, map.getSize());
Danny Hoek
  • 420
  • 4
  • 14
  • 1
    Note that `view.getView2D()` is gone now. This should be updated to read `map.getView().fitExtent(extent, map.getSize())`. – Tim Schaub Nov 11 '14 at 20:25
  • 2
    fitExtent removed in v3.7. check [my answer](http://stackoverflow.com/a/31288818/813951) for the new solution – Mister Smith Jul 08 '15 at 09:34
3
var source = layer.getSource();
goog.events.listen(source, ol.source.VectorEventType.ADD, function(evt) {
     // taken from ol/source/vectorsource.js
     var extent = ol.extent.createEmpty();
     var geometry = null;
     var feature;
     var features = source.getFeatures().getArray();
     for (var i = 0, ii = features.length; i < ii; ++i) {
         feature = features[i];
         geometry = feature.getGeometry();
         if (!goog.isNull(geometry)) {
               ol.extent.extend(extent, geometry.getExtent());
     }
     // here you should have your extent
    }
}, false, this);

Untested.

There should be more elegant way, but I'm not sure right now, where to find it.

nachtigall
  • 2,447
  • 2
  • 27
  • 35
Jachym
  • 309
  • 1
  • 10
  • I've tried to use this code but I get TypeError: ol.source.VectorEventType is undefined. I'm using http://ol3js.org/en/master/build/ol.js - is there a better place to get it? – Tim T Jan 11 '14 at 19:53
2

Since I can't comment yet, I'll have to post another answer: Danny Hoek's answer is not correct anymore, here is the update:

var view = yourmap.getView();
var extent = yourlayer.getSource().getExtent();

view.fitExtent(extent, yourmap.getSize());

Basically that 2D prop seems to be gone.

Stuart Allen
  • 691
  • 6
  • 15
0

There is a getExtent() function on ol.source now, so I'm able to call <layer>.getSource().getExtent(). I can't figure out how to get my map to zoom to that level, however. <map>.zoomToExtent(extent) no longer exists.

Tyler DeWitt
  • 23,366
  • 38
  • 119
  • 196