Leaflet.js 如何向 IIFE 函数添加 javascript 插件

Leaflet.js How to add a javascript addon to IIFE function

我继承了这个 IIFE javascript 功能,并负责添加 markerCluster 插件。但是我找不到任何示例来说明如何将它添加到这样的函数中。

函数如下:

var map = function() {
    var self = {
        config: {
            circleMarker: function(point, feature) {
                return new L.circleMarker(point, {
                    fillColor: "#DA3248",
                    fillOpacity: 0.8,
                    color: "white",
                    radius: 9,
                    className: "event-marker campaign-" + feature.properties.campaign_name +
                        " event-accessible-" + (feature.properties.is_accessible ? "y" : "n")
                });
            },
            Marker: function(point, feature) {
                return new L.circleMarker(point, {
                    fillColor: "#2B9CD9",
                    fillOpacity: 1.0,
                    color: "white",
                    radius: 9,
                    strokeWidth: 1,
                    className: "event-marker campaign-" + feature.properties.campaign_name + " event-accessible-" + (feature.properties.is_accessible ? "y" : "n")
                });
            },
            tileLayer: new L.tileLayer('https://{s}.tiles.mapbox.com/v4/mapbox.streets/{z}/{x}/{y}.png?access_token=' + MAPBOX_TOKEN, {
                attribution: '<a href="http://www.openstreetmap.org/copyright" target="_blank">&copy; OpenStreetMap contributors</a>'
            })
        },
        data: {},
        init: function() {
            self.init_map();
            self.lc = L.control.locate({
                keepCurrentZoomLevel: false,
                locateOptions: {
                maxZoom: 10
                },
                strings: {
                    title: "Locate me"
                    }
            }).addTo(self.map);
        },
        init_map: function() {
            self.map = new L.Map("map", {
                center: [37.8, -96.9],
                zoom: self.get_init_zoom(),
                tap: false
            }).addLayer(self.config.tileLayer);
            self.load_event_data();
            self.load_zip_codes();
            self.bind_events();
            self.handle_filter_params();
        },
        handle_filter_params: function() {
            var event_types = new URLSearchParams(window.location.search).get("event_types");
            if (event_types == null) {
                return;
            }
            event_types = event_types.split(',');
            var filters = document.querySelectorAll('#filter-type-list input[name="type[]"]');
            for (var i = 0; i < filters.length; i++) {
                var filter = filters[i];
                if (event_types.indexOf(filter.getAttribute('id')) == -1) {
                    filter.click();
                }
            }
        },
        bind_events: function() {
            document.getElementById('zipcode').addEventListener('keyup', self.handle_zipcode_keydown);
            document.getElementById('filter-type-list').addEventListener('click', self.handle_filter_type_click);
            document.getElementById('distance').addEventListener('change', self.handle_radius_change);
            self.map.on('moveend', self.filter_events_by_viewport);
            self.map._container.addEventListener('mouseover', self.handle_map_hover);
            self.map._container.addEventListener('mouseout', self.handle_map_mouseout);
        },
        is_mobile: function() {
            return window.navigator.userAgent.toLowerCase().indexOf('mobile') !== -1;
        },
        get_init_zoom: function() {
            if (!self.is_mobile()) {
                return 4;
            } else {
                return 3;
            }
        },
        filter_events_by_viewport: function() {
            if (self.map.getZoom() < 8) {
                self.clear_events_list();
            } else {
                var center = self.map.getCenter();
                var bounds = self.map.getBounds();
                var events = [];
                window.bounds = bounds;
                for (var i = 0; i < self.data.events.features.length; i++) {
                    var event = self.data.events.features[i];
                    var coords = event.geometry.coordinates;
                    var p = L.latLng(coords[1], coords[0]);
                    if (bounds.contains(p)) {
                        events.push(event);
                    }
                }
                events = self.sort_by_distance(events, center);
                self.data.filtered_events = events;
                self.populate_events_list();
            }
        },
        sort_by_distance: function(events, center) {
            for (var i = 0; i < events.length; i++) {
                var event = events[i];
                event.distance = center.distanceTo(L.latLng(event.geometry.coordinates[1], event.geometry.coordinates[0]));
            }
            events.sort(function(a, b) {
                return a.distance - b.distance
            });
            return events;
        },
        handle_filter_type_click: function() {
            if (event.target.tagName != 'INPUT') {
                return;
            }
            var events_list = document.getElementById('events-list');
            var event_accessible_id = 'event_accessible';
            var event_accessible_toggle_class = 'event-show-accessible';
            if (event.target.id == event_accessible_id) {
                self.map._container.classList.toggle(event_accessible_toggle_class);
                events_list.classList.toggle(event_accessible_toggle_class);
            } else if (event.target.checked) {
                self.map._container.classList.remove('hide-campaign-' + event.target.value);
                events_list.classList.remove('hide-campaign-' + event.target.value);
            } else {
                self.map._container.classList.add('hide-campaign-' + event.target.value);
                events_list.classList.add('hide-campaign-' + event.target.value);
            }
        },
        handle_radius_change: function(event) {
            if (event.target.tagName != 'SELECT') {
                return;
            }
            var value = event.target.options[event.target.selectedIndex].value;
            if (value == "5") {
                self.map.setZoom(12);
            } else if (value == "20") {
                self.map.setZoom(10);
            } else if (value == "50") {
                self.map.setZoom(9);
            } else if (value == "100") {
                self.map.setZoom(6);
            }
        },
        handle_zipcode_keydown: function(event) {
            if (event.target.value.length != 5) {
                return;
            }
            var latlng = self.data.zipcodes[event.target.value];
            if(latlng != undefined){
                self.map.setView(new L.LatLng(latlng[0], latlng[1]), 9, {
                    pan: true
                });
            }
        },
        load_event_data: function() {
            self.xhr('GET', events_url, function(xhr) {
                var newJson = JSON.parse(xhr.responseText);
                var oldJson = {};
                oldJson["type"]="FeatureCollection";
                oldJson["features"] = [];
                for (var i = 0; i < newJson.data.length; i++) {

                    if(newJson.data[i]['location'] != undefined) {
                        var address1="";
                        var address2="";
                        if(newJson.data[i]['location']['address_lines'] != undefined){
                           address1= newJson.data[i]['location']['address_lines'][0];
                           address2= newJson.data[i]['location']['address_lines'][1];
                        }
                        var city="";
                        if(newJson.data[i]['location']['locality'] != undefined){
                            city = newJson.data[i]['location']['locality'];
                        }
                        var postal_code="";
                        if(newJson.data[i]['location']['postal_code'] != undefined){
                            postal_code = newJson.data[i]['location']['postal_code'];
                        }
                        var region="";
                        if(newJson.data[i]['location']['region'] != undefined){
                            region = newJson.data[i]['location']['region'];
                        }
                        var start_time="";
                        var end_time="";
                        if(newJson.data[i]['timeslots'][0] != undefined){
                            var lengthOfTimeslots=newJson.data[i]['timeslots'];
                            start_time = newJson.data[i]['timeslots'][0]['start_date'];
                            if(newJson.data[i]['timeslots'][lengthOfTimeslots-1] != undefined && newJson.data[i]['timeslots'][lengthOfTimeslots-1]['end_date'] != undefined ){
                                end_time = newJson.data[i]['timeslots'][lengthOfTimeslots-1]['end_date'];
                            }else{
                                end_time = newJson.data[i]['timeslots'][0]['end_date'];
                            }
                        }
                        var features = {
                            "type": "Feature",
                            "properties": {
                                "id": newJson.data[i]['id'],
                                "campaign_name": newJson.data[i]['event_type'],
                                "title": newJson.data[i]['title'],
                                "starts_at": (new Date(start_time*1000)).toLocaleString("en-US", {timeZone: newJson.data[i]['timezone']}),
                                "ends_at": (new Date(end_time*1000)).toLocaleString("en-US", {timeZone: newJson.data[i]['timezone']}),
                                "is_accessible": true,
                                "status":"active",
                                "address1": address1,
                                "address2": address2,
                                "city": city,
                                "state": region,
                                "is_private":false,
                                "venue":"Private",
                                "starts_at_utc":(new Date(start_time*1000)).toUTCString(),
                                "ends_at_utc":(new Date(end_time*1000)).toUTCString(),
                                "zip": postal_code
                            },
                            "geometry": {
                                "type": "Point",
                                "coordinates": [
                                    newJson.data[i]['location']['location']['longitude'],
                                    newJson.data[i]['location']['location']['latitude']
                                ]
                            },
                        };
                        oldJson["features"].push(features);
                    }
                }

                self.data.events = oldJson;
                L.geoJson(self.data.events, {
                    pointToLayer: function(feature, latlng) {
                        if (['-town-hall', '-rally-campaign'].indexOf(feature.properties.campaign_name) !== -1) {
                            return self.config.Marker(latlng, feature);
                        } else {
                            return self.config.circleMarker(latlng, feature);
                        }
                    },
                    onEachFeature: function(feature, layer) {
                        var tpl = document.getElementById('popup-template').innerHTML;
                        var event = feature.properties;
                        layer.bindPopup(eval("`" + tpl + "`"), {
                            className: 'event',
                            maxWidth: 260
                        });
                        layer.addTo(self.map);
                    }
                }).addTo(self.map);
            });
        },
        load_zip_codes: function() {
            self.xhr('GET', zipcodes_url, function(xhr) {
                self.data.zipcodes = JSON.parse(xhr.responseText);
            });
        },
        clear_events_list: function() {
            var events_list = document.getElementById('events-list');
            while (events_list.firstChild) {
                events_list.removeChild(events_list.firstChild);
            }
        },
        populate_events_list: function() {
            self.clear_events_list();
            var tpl = document.getElementById('event-template').innerHTML;
            var events_list_frag = document.createDocumentFragment();
            for (var i = 0; i < self.data.filtered_events.length; i++) {
                var event = self.data.filtered_events[i].properties;
                var item = document.createElement('li');
                item.setAttribute('class', 'event campaign-' + event.campaign_name + " event-accessible-" + (event.is_accessible ? "y" : "n"));
                item.innerHTML = eval("`" + tpl + "`");
                item.setAttribute('data-id', event.id);
                item.setAttribute('data-date', moment(event.starts_at_utc).format("X"));
                var coords = self.data.filtered_events[i]['geometry']['coordinates'];
                item.setAttribute('data-point', JSON.stringify(coords));
                events_list_frag.appendChild(item);
            }
            var events_list = document.getElementById('events-list');
            events_list.appendChild(events_list_frag);
        },
        xhr: function(method, url, callback, data) {
            if (typeof data == "undefined") {
                data = null;
            }
            var xhr = new XMLHttpRequest();
            xhr.open(method, url);
            xhr.send(data);
            xhr.onreadystatechange = function() {
                if (xhr.readyState == 4) {
                    callback(xhr);
                }
            }
        },
        signup_url: function(event) {
            var base = "https://www.mobilize.us/event/";
            return base + event.id;
        }
    };
    self.init();
}();

我已尝试通过在此处编辑来添加集群:

init: function() {
            self.init_map();
            self.lc = L.control.locate({
                keepCurrentZoomLevel: false,
                locateOptions: {
                maxZoom: 10
                },
                strings: {
                    title: "Locate me"
                    }
            }).addTo(self.map);
            self.cluster = L.markerClusterGroup({ disableClusteringAtZoom: 17 });
        },

这里:

onEachFeature: function(feature, layer) {
                        var tpl = document.getElementById('popup-template').innerHTML;
                        var event = feature.properties;
                        layer.bindPopup(eval("`" + tpl + "`"), {
                            className: 'event',
                            maxWidth: 260
                        });
                        cluster.addLayer(layer);
                        layer.addTo(self.map);
                    }
                }).addTo(self.map).addLayer(cluster);

但是显示cluster没有定义。我不得不承认,我不熟悉 IIFE 函数,我怀疑我对 cluster 的放置不正确。

将您的函数括在括号中,如下所示

var map = (function(cluster) {

//your code

})(cluster);

要将插件添加到您的 IIFE,您应该在 init 函数下再创建一个函数,并像这样实例化插件:

...
cluster: function() {
       var markers = L.markerClusterGroup();
       for (var i = 0; i < addressPoints.length; i++) {
            var a = addressPoints[i];
            var title = a[2];
            var marker = L.marker(new L.LatLng(a[0], a[1]), {
                title: title
            });
            marker.bindPopup(title);
            markers.addLayer(marker);
       }
       self.map.addLayer(markers);
},
...

然后在 init 函数中调用它

init_map: function() {
    self.map = new L.Map("map", {
       center: [37.8, -96.9],
       zoom: self.get_init_zoom(),
       tap: false
    }).addLayer(self.config.tileLayer);
    /*             self.load_event_data();
    self.load_zip_codes();
             */
    //self.bind_events();
    //self.handle_filter_params();

    // invoke the function here
    self.cluster();
},

我临时评论了一些其他函数调用,因为返回了一些错误只是为了能够重现问题和 运行 代码。

如果您平移地图并转到新西兰,您将看到与插件演示页面中的示例完全一样的标记簇。

Demo