Howto support multiple Leaflet maps on the same page?

2,153 views
Skip to first unread message

Johan Dahlberg

unread,
Jun 11, 2015, 8:14:56 AM6/11/15
to leafl...@googlegroups.com
Hi!

I am working on a wrapper for Leaflet as a module but I am having trouble when I have multiple maps on the same page. I have attached the module in the end of this post as well as how it's used. When I use one of the maps and then change tab (jQuery tabs) and show another map and then go back to the first map the first map shows the same markers as before but show the map from the second one. I don't know if the problem is that I use Prototype wrong way so that the variables are shared or that the problem has with how I use Leaflet to do.

Anyone that has used multiple maps on the same page?

Usage:
leafletMapObj = new LeafletMap("mapId");
leafletMapObj.init({});
leafletMapObj.move(responseData.position.lat, responseData.position.lng);
leafletMapObj.addMarker(responseData.position.lat, responseData.position.lng, {}, {});


Module;
require.config({
    paths: {
        'leaflet': '../bower_components/leaflet/dist/leaflet',
        'leaflet.awesome-markers': '../bower_components/Leaflet.awesome-markers/dist/leaflet.awesome-markers',
        'leaflet.markercluster': '../bower_components/leaflet.markercluster/dist/leaflet.markercluster',
        'lodash':  '../bower_components/lodash/lodash.min',
    },
    shim: {
        "leaflet": {
            exports: 'L'
        },
        'leaflet.awesome-markers': {
            deps: ['leaflet'],
            exports: 'L.AwesomeMarkers'
        },
        'leaflet.markercluster': {
            deps: ['leaflet'],
            exports: 'L.markerClusterGroup'
        }
    }
});

define(["leaflet", "lodash", "leaflet.awesome-markers", "leaflet.markercluster"], function(L, _) {
    var defaults = {
        lat: 51.505,
        lng: -0.09,
        zoom: 13
    };

    var defaultIcon = {
        icon: 'bus',
        iconColor: 'white',
        markerColor: 'blue',
        prefix: 'fa' // Font Awesome, alt. glyphicon
    };
    var defaultMapOptions = {
        center: new L.LatLng(defaults.lat, defaults.lng),
        layers: L.tileLayer('http://otile1.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}.jpg', {
            attribution: 'Tiles Courtesy of <a href="http://www.mapquest.com/" target="_blank">MapQuest</a> <img src="http://developer.mapquest.com/content/osm/mq_logo.png">'
        })
    };
    var defaultShapePath = {
        className: '',
        clickable: true,
        color: '#B00303', //'#03f',
        dashArray: null,
        fill: true,
        fillColor: '#9F4700', //'#03f',
        fillOpacity: 0.5,
        fillRule: 'evenodd',
        lineCap: null,
        lineJoin: null,
        opacity: 0.5,
        stroke: true,
        weight: 5
    };
    var defaultMarker = {
        draggable: false,
        riseOnHover: false
    };

    function LeafletMap(id) {
        this.mapId = id;
        this.map = null;
        this.lat = defaults.lat;
        this.lng = defaults.lng;
        this.zoomLvl = defaults.zoom;

        //this.markers = new L.FeatureGroup();
        this.markers = new L.markerClusterGroup({
            iconCreateFunction: function(cluster) {
                var childCount = cluster.getChildCount();
                var healthCount = 0;

                _.forEach(cluster._markers, function(marker, key) {
                    if (marker._popup._content.substring(0, 30) == "<div style=\"display:none\">true") {
                        healthCount++;
                    }
                });

                var c = ' marker-cluster-';
                if (childCount === healthCount) {
                    c += 'small';
                } else if (healthCount === 0) {
                    c += 'medium';
                } else {
                    c += 'large';
                }

                return new L.DivIcon({ html: '<div><span>' + healthCount + '/' + childCount + '</span></div>', className: 'marker-cluster' + c, iconSize: new L.Point(40, 40) });
            },
            showCoverageOnHover: true,
            spiderfyOnMaxZoom: true,
            zoomToBoundsOnClick: true
        });
        this.shapes = new L.FeatureGroup();
    }

    LeafletMap.prototype.addCircle = function(lat, lng, radius, options) {
        var path = _.extend(defaultShapePath, options.path);
        var circle = L.circle([lat, lng], radius, path);

        this.shapes.addLayer(circle);
    };

    LeafletMap.prototype.addListener = function(type, callback) {
        this.map.on(type, callback);
    };

    LeafletMap.prototype.addMarker = function(lat, lng, iconOptions, options) {
        var newIcon = _.extend(defaultIcon, iconOptions);
        var markerSettings = _.extend(defaultMarker, options);

        var marker = L.marker([lat, lng], {
            draggable: markerSettings.draggable,
            icon: L.AwesomeMarkers.icon(newIcon),
            riseOnHover: markerSettings.riseOnHover
        });

        if(options.events !== undefined || options.events !== null) {
            _.forEach(options.events, function(event, key) {
                marker.on(event.type, event.callback);
            });
        }

        this.markers.addLayer(marker);
    };

    LeafletMap.prototype.addMarkerWithPopup = function(lat, lng, text, iconOptions) {
        var newIcon = _.extend(defaultIcon, iconOptions);
        var marker = L.marker([lat, lng], { icon: L.AwesomeMarkers.icon(newIcon) })
            .bindPopup(text);
        this.markers.addLayer(marker);
    };

    LeafletMap.prototype.autoZoom = function() {
        var bounds = this.markers.getBounds();
        bounds.extend(this.shapes.getBounds());
        this.map.fitBounds(bounds);
    };

    LeafletMap.prototype.clearMarkers = function() {
        this.markers.clearLayers();
    };

    LeafletMap.prototype.clearShapes = function() {
        this.shapes.clearLayers();
    };

    LeafletMap.prototype.init = function(options) {
        var mapOptions = _.extend(defaultMapOptions, options);
        this.map = L.map(this.mapId, mapOptions)
            .setZoom(this.zoomLvl)
            .addLayer(this.markers)
            .addLayer(this.shapes);
    };

    /*
     * Used when coming from display: none to prevent grey tiles.
     */
    LeafletMap.prototype.invalidateSize = function() {
        this.map.invalidateSize();
    };

    LeafletMap.prototype.move = function(lat, lng) {
        this.lat = lat;
        this.lng = lng;
        this.map.panTo([this.lat, this.lng], this.zoomLvl);
    };

    LeafletMap.prototype.zoom = function(zoomLvl) {
        this.zoomLvl = zoomLvl;
        this.map.setZoom(this.zoomLvl);
    };

    return LeafletMap;
});



Johan Dahlberg

unread,
Jun 12, 2015, 2:58:30 AM6/12/15
to leafl...@googlegroups.com
I solved it after a while. The problem was that I created the TileLayer in defaultMapOptions. It worked when I moved that two the init property.

/Johan
Reply all
Reply to author
Forward
0 new messages