1 year ago

#331485

test-img

gcbox999

How to display markerClusters by axios props with Vue 3 and vue-Leaflet?

I have a problem to display the markerClusters after receive by props in my component Map :

 <template>
  <div>
    <LMap
      v-show="showLoading"
      class="map"
      ref="map"
      :center="center"
      :zoom="zoom"
      :maxZoom="max"
      :minZoom="min"
      :options="{ attributionControl: false }"
      @ready="onLeafletReady"
      :zoomAnimation="true"
      :markerZoomAnimation="true"
      :useGlobalLeaflet="true"
    >
      <template v-if="leafletReady">
        <LTileLayer
          v-for="tileProvider in tileProviders"
          :attribution="tileProvider.attribution"
          :key="tileProvider.name"
          layer-type="base"
          :name="tileProvider.name"
          :url="tileProvider.url"
          :visible="tileProvider.visible"
        >
        </LTileLayer>

        <LControlScale position="bottomleft" :imperial="false" :metric="true" />
        <LControlAttribution position="bottomright" prefix="FTM" />
        <LControlLayers />
        <div class="loader" v-if="loading" />
      </template>
    </LMap>
  </div>
</template>

<script>
import { defineComponent, ref } from "vue"
import * as L from "leaflet"
import "leaflet.markercluster/dist/leaflet.markercluster.js"
import "leaflet/dist/leaflet.css"
import "leaflet.markercluster/dist/MarkerCluster.css"
import "leaflet.markercluster/dist/MarkerCluster.Default.css"
import {
  LControlAttribution,
  LControlLayers,
  LControlScale,
  LMap,
  LTileLayer
} from "@vue-leaflet/vue-leaflet"

export default defineComponent({
  components: {
    LControlAttribution,
    LControlLayers,
    LControlScale,
    LMap,
    LTileLayer
  },
  props: {
    pois: {
      type: Array,
      default: null
    }
  },

  setup() {
    return {
      showLoading: ref(true),
      zoom: ref(7),
      center: ref({ lat: 48.85664, lng: 2.35347 })
    }
  },

  data() {
    return {
      leafletReady: false,
      poiMarkersGroup: null,
      attribution:
        '&copy; <a target="_blank" href="http://osm.org/copyright">OpenStreetMap</a> contributors',
      max: 19,
      min: 6,
      tileProviders: [
        {
          name: this.$t("map.mapTiles.standard"),
          visible: true,
          maxZoom: 19,
          attribution:
            '&copy; <a target="_blank" href="http://osm.org/copyright">OpenStreetMap</a> contributors',
          url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        },
        {
          name: this.$t("map.mapTiles.satellite"),
          visible: false,
          maxZoom: 17,
          url: "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
          attribution:
            "Tiles &copy; Esri &mdash; Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community"
        },
        {
          name: this.$t("map.mapTiles.urbanTransport"),
          visible: false,
          maxZoom: 20,
          attribution:
            '&copy; OpenStreetMap France | &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
          url: "https://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png"
        },
        {
          name: this.$t("map.mapTiles.cyclePaths"),
          visible: false,
          maxZoom: 20,
          attribution:
            '<a href="https://github.com/cyclosm/cyclosm-cartocss-style/releases" title="CyclOSM - Open Bicycle render">CyclOSM</a> | Map data: &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
          url: "https://{s}.tile-cyclosm.openstreetmap.fr/cyclosm/{z}/{x}/{y}.png"
        }
      ],
      url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
    }
  },

  methods: {
    async onLeafletReady(_map) {
      await this.$nextTick()
      this.leafletReady = true
    },

    compilClusters(pois, nbPois) {
      L.Map.addInitHook(function () {
        const markerCluster = L.markerClusterGroup({
          removeOutsideVisibleBounds: true,
          chunkedLoading: true,
          showCoverageOnHover: false
        }).addTo(this)
        let markers = []
        for (let i = 0; i < nbPois; i++) {
          const marker = L.marker(L.latLng(pois[i].coords))
          marker.bindPopup(
            "<ul style='padding: 0; list-style-type: none;'>" +
              "<li style='font-weight: bold;'>" +
              pois[i].name +
              "<li>" +
              pois[i].address +
              "</li>" +
              "</li>" +
              "<li>" +
              pois[i].postalCode +
              " " +
              pois[i].city +
              "</li>" +
              "</ul>"
          )
          markers.push(marker)
          markerCluster.addLayers(markers)
        }
      })
    }
  },

  watch: {
    pois(val) {
      if (val !== null) {
        this.compilClusters(val, val.length)
      }
    }
  }
})
</script>

<style lang="scss" scoped>
.map {
  width: 100%;
  height: 100%;
  height: 100vh;
}
</style>

I'm using Quasar+leaflet+@vue-leaflet/vue-leaflet and leaflet.markercluster. I guess based on code https://codesandbox.io/s/vue-3-leaflet-marker-cluster-poc-forked-ns238?file=/components/TestMap.vue:2715-3306

When I send the latlng by props, the coordinates are passed to the compilClusters(latLng, nbOfLatLng) function through the watch() function.

But they are not displayed, if I reload my page, they are displayed!

How to display it when I receive them by props?

vue.js

leaflet

leaflet.markercluster

0 Answers

Your Answer

Accepted video resources