Drawing an OpenLayers 3 map in a hidden element
Asked Answered
F

2

9

I am writing a page where you can view both details about an area and a map. The details are on one tab and the map on another. The relevant portion of the HTML is below and the classes are from Bootstrap.

<div class="col-xs-8">
    <ul class="nav nav-tabs">
        <li class="active"><a href="#tab-details" data-toggle="tab">Details</a></li>
        <li><a href="#tab-map" data-toggle="tab">Map</a></li>
    </ul>
    <div class="tab-content">
        <div id="tab-details" class="tab-pane fade in active"></div>
        <div id="tab-map" class="tab-pane fade">
            <div id="map-container" class="map"></div>
        </div>
    </div>
</div>

The tile layer is from OSM and the vector layer is loaded via a URL serving a KML file. It does this using OpenLayers 3.0.0 as follows:

function ShowMap() {
    var area = $('#AreaCode').val();
    $('#map-container').empty();
    if (area != null && area != '') {
        var kmlUrl = '/kml?code=' + area;
        var tile = new ol.layer.Tile({ source: new ol.source.OSM() });
        var vectorSource = new ol.source.KML({ url: kmlUrl, projection: 'EPSG:3857' });
        var vector = new ol.layer.Vector({ source: vectorSource });
        vector.setOpacity(.3);
        var map = new ol.Map({
            target: 'map-container',
            layers: [tile, vector],
            view: new ol.View({
                center: [0, 0],
                zoom: 2
            })
        });

        vector.addEventListener("change", function(event) {
            map.getView().fitExtent(vectorSource.getExtent(), map.getSize());
        });
    }
}

$('#tab-map-link').on('shown.bs.tab', function(event) {
    ShowMap();
});

This renders the map when the map tab is clicked causing a small delay. Is there any way of loading it even when the tab is not selected? If I try that and don't redraw when the map tab is selected then the canvas is blank when I switch to the map tab and only the zoom in and out buttons are shown.

Is there any way to render the map in an element which is not visible?

Flanna answered 25/9, 2014 at 9:14 Comment(2)
I'm a little late to seeing this, but have you tried rendering it full-size but off-screen (eg, via left:-3000px), then moving it into position when switching to your tab?Cheder
@kwah. Thanks for the suggestion. I'd pretty much forgotton about the issue. The code has moved on a bit now anyway (consuming GeoJSON calculated from a PostgreSQL geometry column rather than KML from a MySQL text column). I've accepted the delay and it's not a huge deal, but I'll attempt your workaround if I revisit the issue.Flanna
B
10

You can initialize the map in a hidden container and then, when the tab is activated, you can call updateSize on the map:

map.updateSize()
Bibliolatry answered 26/9, 2014 at 12:38 Comment(1)
Thanks, this will work well for many cases but for me has issues. The problem is that I am now creating a vector source and calling fitExtent to zoom into the vector. This is reset when I call map.updateSize(). Making the map and source available to the tab change event (shown.bs.tab) means making them global variables where they are currently local. I'm going to update my question with further details.Flanna
A
1

In my case the solution was to use the timeout to wait for the div to be displayed.

setTimeout(function() {
    map.updateSize();
}, 100);
Accusation answered 23/3, 2020 at 16:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.