[GIS] OpenLayers 3 Zoom to extent only working in debug

extentsjavascriptopenlayers

I am using GPX data to display routes with OpenLayers 3 and my attempts of zooming to fit the GPS trace have been thus far unsuccessful. I only ever got it working in debug mode on Firefox, where it always zooms correctly, however when just loading the web page nothing happens. Also when drag-dropping a GPX file on the maps the zoom works again, but the same code without projection transformation does not work when displaying the original GPX without the dragAndDropInteraction interaction.

Here is the code snippet that is supposed to make the map zoom to fit the trace:

   //fit view
    var extent = vector.getSource().getExtent();
    var mapProjection = map.getView().getProjection();    
    ConvertedExtent = ol.proj.transformExtent(extent, 'EPSG:3857', 'EPSG:4326'); 
    mapSize = map.getSize();
    map.getView().fitExtent(extent, mapSize);

After calling .getSource().getExtent() the extent array contains the following:
[1215055.5815933049, 6137851.406357965, 1286274.229579136, 6175156.521239913]
which I transform to:
[10.91503, 48.185981, 11.554798, 48.40892199999999]

In Chrome for some reason the extent array contains infinite values:
extent = [ Infinity Infinity -Infinity -Infinity]

function CreateDriveMap(urlToXml)
{
    var transformedCenter = ol.proj.transform(centerPos, 'EPSG:4326', 'EPSG:3857');

    // PROJECTION
    var projection = ol.proj.get('EPSG:3857');

    // SOURCE
    var source = new ol.source.OSM();

    // TILE
    // layer sources that provide pre-rendered, tiled images in grids 
    // that are organized by zoom levels for specific resolutions.
    layer = new ol.layer.Tile({
        source: source,
        name: 'OpenStreetMap'
    });

    // VIEW
    view = new ol.View({
        center: transformedCenter,
        zoom: 5
    });

    // STYLE
    var style = {
        'Point': [new ol.style.Style({
            image: new ol.style.Circle({
                fill: new ol.style.Fill({
                    color: 'rgba(255,255,0,0.4)'
                }),
                radius: 2,
                stroke: new ol.style.Stroke({
                    color: '#f00',
                    width: 1
                })
            })
        })],
        'MultiPoint': [new ol.style.Style({
            image: new ol.style.Circle({
                fill: new ol.style.Fill({
                    color: 'rgba(255,0,255,0.5)'
                }),
                radius: 5,
                stroke: new ol.style.Stroke({
                    color: '#f0f',
                    width: 1
                })
            })
        })],
        'LineString': [new ol.style.Style({
            stroke: new ol.style.Stroke({
                color: 'rgba(255,0,0,0.7)',
                width: '3'
            })
        })],
        'MultiLineString': [new ol.style.Style({
            stroke: new ol.style.Stroke({
                color: '#0f0',
                width: 'rgba(255,0,0,0.7)'
            })
        })],
        'Polygon': [new ol.style.Style({
            fill: new ol.style.Fill({
                color: 'rgba(0,255,255,0.5)'
            }),
            stroke: new ol.style.Stroke({
                color: '#0ff',
                width: 1
            })
        })],
        'MultiPolygon': [new ol.style.Style({
            fill: new ol.style.Fill({
                color: 'rgba(0,0,255,0.5)'
            }),
            stroke: new ol.style.Stroke({
                color: '#00f',
                width: 1
            })
        })]
    };

    // Style Function
    var styleFunction = function (feature, resolution) {
        var featureStyleFunction = feature.getStyleFunction();
        if (featureStyleFunction) {
            return featureStyleFunction.call(feature, resolution);
        } else {
            return defaultStyle[feature.getGeometry().getType()];
        }
    };

    // GPX layer
    var vector = new ol.layer.Vector({
        source: new ol.source.GPX({
            projection: projection,
            url: urlToXml                //'data/gpx/fells_loop.gpx'
        }),
        style: function (feature, resolution) {
            return style[feature.getGeometry().getType()];
        }
    });


    // CREATE MAP
    var map = new ol.Map({
        // targeted div
        target: 'map',

        // the layers 
        layers: [layer, vector],

        // the view 
        view: view,

        //projection: new OpenLayers.Projection("EPSG:900913"),
        projection: projection

        // interactions
        //interactions: ol.interaction.defaults().extend([dragAndDropInteraction])
    });


    //var View = map.getView();
      // View.fitExtent(vector.getExtent(),  /* @type {ol.Size} */ (map.getSize()));

    // CENTER & PUT START MARKER, DOES NOT WORK
    // ol.Layer.events.register("loadend", vector, function () {
    //    this.map.zoomToExtent(this.getDataExtent());
    //    var startPoint = this.features[0].geometry.components[0];
    //    layerMarkers.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(startPoint.x, startPoint.y), icon));
    //});

    // Add controls
    var zoomslider = new ol.control.ZoomSlider();
    map.addControl(zoomslider);
    var scaleLine = new ol.control.ScaleLine();
    map.addControl(scaleLine);

    //FIT VIEW TO GPX
    var extent = vector.getSource().getExtent();
    var mapProjection = map.getView().getProjection();
    ConvertedExtent = ol.proj.transformExtent(extent, 'EPSG:3857', 'EPSG:4326'); 
    mapSize = map.getSize();
    map.getView().fitExtent(extent, mapSize);

    // STYLE FUNCTION
    var stylefunction = function (feature, resolution) {
        var featurestylefunction = feature.getstylefunction();
        if (featurestylefunction) {
            return featurestylefunction.call(feature, resolution);
        } else {
            return style[feature.getgeometry().gettype()];
        }
    };

    // DRAG & DROP
    var dragAndDropInteraction = new ol.interaction.DragAndDrop({
        formatConstructors: 
            [
              ol.format.GPX,
              ol.format.GeoJSON,
              ol.format.IGC,
              ol.format.KML,
              ol.format.TopoJSON
            ]
    });

    dragAndDropInteraction.on('addfeatures', function (event) {
        var vectorSource = new ol.source.Vector({
            features: event.features,
            projection: event.projection
        });
        map.getLayers().push(new ol.layer.Vector({
            source: vectorSource,
            style: styleFunction
        }));
        var view = map.getView();
        view.fitExtent(
            vectorSource.getExtent(), /** @type {ol.Size} */ (map.getSize()));
    });
}

Best Answer

I had a similar problem in version 3.8.2. I solved it by putting getExtent into the event:

vector.getSource().on("change", function(evt) {
    extent = vector.getSource().getExtent();
    map.getView().fit(extent, map.getSize());
});

In older version you just use fitExtent instead of fit.