user10753862
user10753862

Reputation:

Display new markers when map bound changed and clear old marker

when map bound moved by user, make disappear old position markers and display new markers.

For an example you can check this map. Markers are moving every time bounds updated and clearing the old position markers. I am exactly trying to do this.

UPDATED 2

what I have done so far is right below. No errors but, still seeing all markers at once..?

data(){
     return {
        bounds:{},
        map: {},
        mapName: "map",
        estates: [], 
     }
},
mounted() {
    axios.get('/ajax').then((response) => {
        this.estates =  response.data
        this.insertMarkers();
    });
    this.initMap();

},
methods: {

            initMap: function() {

        this.bounds = new google.maps.LatLngBounds(
            new google.maps.LatLng(34.652500, 135.506302),
        );

        var mapOptions = {
            mapTypeId: 'roadmap',
            center: new google.maps.LatLng(0, 0),
            zoom: 8
        };


        let self = this;

        this.map = new google.maps.Map(document.getElementById(this.mapName), mapOptions);

        var boundsListener = google.maps.event.addListener((this.map), 'bounds_changed', function(event) {

            self.getMarkers();

        });

        this.map.fitBounds(this.bounds);
    },

    getMarkers: function() {

        let bounds = this.map.getBounds();

        let southWest = bounds.getSouthWest();
        let northEast = bounds.getNorthEast();
        console.log(southWest);

        axios.get('/ajax', {
            params: {
                fromLat: southWest.lat()-0.01,
                toLat: northEast.lat()-0.01,
                fromLng: southWest.lng()+0.01,
                toLng: northEast.lng()+0.01,
            }
        }).then((response) => {
            this.estates = response.data;
            this.updateMarkers();
        });

    },

    updateMarkers: function() {


        google.maps.event.addListener(map, 'idle', function() {

            var map = this.map;
            var estates = this.estates;
            let i = 0;

            for (i = 0; i < this.markers.length; i++) {
                this.markers[i].setMap(null);
            }

            this.markers = [];

            for (i = 0; i < estates.length; i++) {

                var position = new google.maps.LatLng(estates[i].lat, estates[i].lng);

                var marker = new google.maps.Marker({
                    position: position,
                    map: map,
                    label: {
                        text:
                            estates[i].price.toString().length == 1 ?
                            estates[i].price.toString().replace("1", "未定") :
                            estates[i].price.toString() + "万",
                        color: '#fff',
                    },
                    icon: '/img/marker.png',
                    url: "/pages/" + estates[i].id,
                });

                this.markers.push(marker);

                google.maps.event.addListener(marker, 'click', function () {
                    window.location.href = this.url;
               });
            }
        });
    },

Upvotes: 2

Views: 2573

Answers (2)

MrUpsidown
MrUpsidown

Reputation: 22490

As I said in my comment, you can do it the other way around. Fetch only markers that are visible within the map viewport. You just need to reorganize your code a bit and modify your database query.

You need to pass a minimum and maximum latitude and longitude to your controller so that you can query the DB for markers between the given latitudes and longitudes. You can get these by getting your map bounds and extracting southwest and northeast lat/lng.

export default {
  data() {
    return {
      bounds: {},
      map: {},
      mapName: "map",
      estates: [],
      markers: [] // Added markers array here
    }
  },
  mounted() {

    this.initMap(); // On "mounted" only call initMap
  },
  methods: {

    initMap: function() {

      //giving specific location of japan.
      this.bounds = new google.maps.LatLngBounds(
        new google.maps.LatLng(34.652500, 135.506302),
      );

      var mapOptions = {
        mapTypeId: 'roadmap',
        center: new google.maps.LatLng(0, 0),
        zoom: 5
      };

      this.map = new google.maps.Map(document.getElementById(this.mapName), mapOptions);

      let self = this;

      var boundsListener = google.maps.event.addListener((this.map), 'idle', function(event) {

        self.getMarkers(); // When map is idle, get markers
      });

      this.map.fitBounds(this.bounds);
    },
    getMarkers: function() {

      // Get current map bounds
      let bounds = this.map.getBounds();
      let southWest = bounds.getSouthWest();
      let northEast = bounds.getNorthEast();

      // Send request with min/max latitude and longitude to only fetch markers for that area
      axios.get('/ajax', {
        params: {
          fromLat: southWest.lat(),
          toLat: northEast.lat(),
          fromLng: southWest.lng(),
          toLng: northEast.lng(),
        }
      }).then((response) => {
        this.estates = response.data;
        this.updateMarkers();
      });
    },

    updateMarkers: function() {

      // Remove previous markers
      for (let i = 0; i < this.markers.length; i++) {
        this.markers[i].setMap(null);
      }

      // Reset markers array
      this.markers = [];

      // Add current markers
      for (i = 0; i < estates.length; i++) {

        var position = new google.maps.LatLng(estates[i].lat, estates[i].lng);

        var marker = new google.maps.Marker({
          position: position,
          map: map,
          icon: '/img/marker.png',
          url: "/pages/" + estates[i].id,
        });

        // Push marker to markers array for future removal
        this.markers.push(marker);
      }
    }
  }
}

In your controller, you need to get the parameters you send with the axios request (fromLat, toLat, etc.)

public function ajax() {

  // Here you need to retrieve the parameters sent by the axios request !
  // And set them as $fromLat, $toLat, etc.

  $data = \DB::table('allestates')
  ->where('lat', '>', $fromLat)
  ->where('lat', '<', $toLat)
  ->where('lng', '>', $fromLng)
  ->where('lng', '<', $toLng)
  ->get();

  $response = response()->json($data);
  return $response;
}

Untested, but that should work. You need to adapt some parts! Read my comments in the code as well.

Note: the bounds_changed event is triggered repeatedly when a user drags the map, so this way you are going to send a lot of requests to your database. Instead, you should probably prefer another event such as idle or delay the trigger of your ajax call somehow to reduce the number of queries.

Upvotes: 3

Abbas Jaber
Abbas Jaber

Reputation: 49

You need to store old Value and compare with new one you need timeout function to update each time iterval ex window.setTimeout(insertMarkers,3000)

for(var i=0, len=res.length; i<len; i++) {

            //Do we have this marker already?
            if(markerStore.hasOwnProperty(res[i].driver_id)) {
                  markerStore[res[i].id].setPosition(new google.maps.LatLng({lat: parseFloat(res[i].lat), lng: parseFloat(res[i].lng)}));
            } else {
                 marker = new google.maps.Marker({
       position:  {lat: parseFloat(res[i].lat), lng: parseFloat(res[i].lng)},
       map:map       
                }); 
      google.maps.event.addListener(marker, 'click', (function(marker, i,id) {
                        return function() {
                            console.log(id)
                        }
                    })(marker, i,id));

                markerStore[res[i].id] = marker;

            }
        }
                markerStore[estate.id] = marker;

            }

    });

UPDATE

mounted() {
.
.
.

this.initMap();
window.setTimeout(this.insertMarkers,3000)

    },
methods: {
.
.
.
insertMarkers: function() {
var marker=[];
var markerStore = {};
    this.estates.forEach((estate, index) => {
 //Do we have this marker already?
            if(markerStore.hasOwnProperty(estate.id)) {
                  markerStore[estate.id].setPosition(new google.maps.LatLng({lat: parseFloat(estate.lat), lng: parseFloat(estate.lng)}));
            } else {
                 marker = new google.maps.Marker({
                     icon: '/img/marker.png',
                    position:  {lat: parseFloat(estate.lat), lng: parseFloat(estate.lng)},
                    map:map       
                }); 
                var es_id=estate.id;
      google.maps.event.addListener(marker, 'click', (function(marker, index,es_id) {
                        return function() {
                            console.log(es_id)
                             window.location.href = "/pages/" + es_id;
                        }
                    })(marker, index,es_id));
                markerStore[estate.id] = marker;
            }

    });

Upvotes: -1

Related Questions