简体   繁体   中英

Can't remove Google Map Markers when reloading data

I'm a having some trouble with google maps V3 API.

Here's my AngularJS Directive:

;
(function () {
"use strict";

angular.module('LoVendoApp.directives')
    .directive('map', ['SimpleRETS', 'InfoWindowService', 'McOptions', 'ModalOptions', '$rootScope', '$parse', '$uibModal', '$timeout', 'SafetyFilter',
        function (SimpleRETS, InfoWindowService, McOptions, ModalOptions, $rootScope, $parse, $uibModal, $timeout, SafetyFilter) {
            return {
                restrict: 'A',
                scope: {
                    requestObj: '='
                },
                link: function (scope, el, attrs) {
                    //Creating map instance with GoogleMaps API
                    var map = new google.maps.Map(el[0], {
                        center: {
                            lat: 25.7742700,
                            lng: -80.1936600
                        },
                        zoom: 8
                    });

                    //Markers array
                    var markers = [];
                    console.log('on init = ', markers.length);

                    /**
                     * Creates new google maps
                     * marker
                     *
                     * @param {Object} param
                     * 
                     */

                    function _newGoogleMapsMarker(param) {
                        var r = new google.maps.Marker({
                            map: param._map,
                            position: new google.maps.LatLng(param._lat, param._lng),
                            title: param._head,
                            icon: param._icon
                        });
                        if (param._data) {
                            google.maps.event.addListener(r, 'click', function () {
                                // this -> the marker on which the onclick event is being attached
                                if (!this.getMap()._infoWindow) {
                                    this.getMap()._infoWindow = new google.maps.InfoWindow();
                                }
                                this.getMap()._infoWindow.close();
                                var content = InfoWindowService.getContent(param._data);

                                this.getMap()._infoWindow.setContent(content);
                                //Creates event listener for InfoWindow insances
                                google.maps.event.addListener(this.getMap()._infoWindow, 'domready', function () {
                                    $("#iw_container")
                                        .off("click")
                                        .on("click", modalListener);
                                    //Opens modal when click is listened
                                    function modalListener() {
                                        var modalOptions = ModalOptions.getHouseDetailOptions(param._data);
                                        var modalInstance = $uibModal.open(modalOptions);
                                    }
                                });
                                this.getMap()._infoWindow.open(this.getMap(), this);
                            });
                        }
                        return r;
                    }
                    //Handling request with SimpleRETS service factory
                    scope.$on('loadMap', function () {
                        SimpleRETS.requestHandler(scope.requestObj).then(dataReceived, dataError);

                        function dataReceived(res) {
                            if (markers.length > 0) {
                                for (var k = 0; k > markers.length; k++) {
                                    markers[k].setMap(null);
                                    console.log('removing! #', k);
                                }
                                markers = [];
                                console.log('removed!');
                            }
                            var results = res.filter(SafetyFilter.filterData);
                            $rootScope.globalHousesData = results;
                            if (markers.length == 0)
                                $timeout(loadMarkers(results), 1000);
                        }

                        function dataError(error) {
                            console.log('mapError', error);
                        }

                    });
                    //Randomizes position for matching coordinates
                    function randomPos() {
                        return Math.random() * (0.0001 - 0.00005) + 0.00005;
                    }

                    function loadMarkers(results) {
                        // Fetching marker options from service
                        var options = McOptions.getOptions;
                        for (var i = 0; i < results.length; i++) {
                            var marker = _newGoogleMapsMarker({
                                _map: map,
                                _icon: 'assets/images/icon.png',
                                _lat: results[i].geo.lat,
                                _lng: results[i].geo.lng,
                                _head: '|' + new google.maps.LatLng(results[i].geo.lat, results[i].geo.lng),
                                _data: results[i]
                            });
                            markers.push(marker);
                        }
                        var markerCluster = new MarkerClusterer(map, markers, options);
                    }
                    //Initializes event to load m
                    scope.$broadcast('loadMap');
                }
            }
        }
    ]);

})();

As you can see I've been going nuts with console.logs to see what is wrong with my logic. It may look a bit overwhelming but I simply have 4 main components or actions. 1st I initialize the map:

 var map = new google.maps.Map(el[0], {
       center: {
          lat: 25.7742700,
          lng: -80.1936600
        },
       zoom: 8
  });

The I instantiate a markers array: var markers = [];

Then I have 2 main functions. One that create new markers: _newGoogleMapMarkers(param)

This function takes a param object that basically contain the map object, position coordinates, an icon, title and some content that should be available in the InfoWindow. Also, I'm attatching an onClick listener to all InfoWindows to open an external modal in my app.

The other function should be triggered when the markers array is empty and it loads the new data from the external API I'm using (SimpleRETS)

This is all triggered by an event `$scope.$broadcast('loadMap') that is triggered everytime filters are changed, the user interacts with some stuff, etc.

The problem is that even though I am calling the loadMarkers() function when the markers array is empty (and after iterating and doing markers[k].setMap(null)), the old markers stay in the map, creating a massive bloab of markers when loading 500 markers with each load. I even tried setting a timeout of 1000ms after the markers array is empty before the next load, to see if it helped in any way, but it doesn't.

So what do you guys think? I'd appreciate any suggestions you might have.

For anyone that might be having the same problem. If you are using the markerclusterer jQuery Plugin you must markerCluster.clearMarkers(); before emptying the markers array after a new load of markers.

So basically it'll end up looking something like this

if (markerCluster) {
     markerCluster.clearMarkers();
     markers = [];
}

//Load new markers in the markers array
[...]
//Creating Cluster
markerCluster = new MarkerClusterer(map, markers, options);

Then you would do whatever you need to fetch data and replace the markers, since from this point on the map would be clear of markers and clusters.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM