Как смонтировать пользовательский компонент Vue в маркеры для L.markerClusterGroup - PullRequest
1 голос
/ 11 июля 2019

Мне нужно визуализировать пользовательские маркеры с помощью всплывающих окон в компоненте Vue.

map

Я использую L.markerClusterGroup и пытаюсь смонтировать пользовательский компонент для маркера и всплывающего окна, но он не работает.

map.js

<template>
  <div id="map" class="map"></div>
</template>

<script>
import L from 'mapbox.js';
import 'mapbox.js/dist/mapbox.css';
import 'leaflet.markercluster';

import Vue from 'vue';
import Pin from './Pin';
import Popup from './Popup';
import config from '@/config';

const EnhancedPin = Vue.extend(Pin);
const EnhancedPopup = Vue.extend(Popup);

export default {
  props: {
    geojson: {
      type: Object,
      required: true,
    },
  },
  mounted() {
    this.initMap();
  },
  methods: {
    initMap() {
      this.createMap(this.geojson);

      this.addClustersToMap(this.geojson);
    },
    createMap(geojson) {
      L.mapbox.accessToken = config.mapBoxKey;

      this.map = L.mapbox
        .map('map', null, {
          attributionControl: { compact: false },
          zoomControl: true,
          minZoom: 1,
        })
        .addLayer(L.mapbox.styleLayer('mapbox://styles/mapbox/streets-v11'));
        .setView([0, 0], 2);
    },
    addClustersToMap(geojson) {
      var clusterGroup = L.markerClusterGroup({
        showCoverageOnHover: false,
        iconCreateFunction: cluster => {
          return L.divIcon({
            className: 'cluster-icon',
            iconSize: 40,
            html: cluster.getChildCount(),
          });
        },
      });

      geojson.features.forEach(feature => {
        var cssIcon = L.divIcon({
          className: 'icon',
          html: '<div class="icon-inner"></div>',
        });
        const popup = L.popup({ minWidth: 220 }).setContent('<div class="popup-inner"></div>');

        const marker = L.marker([feature.geometry.coordinates[1], feature.geometry.coordinates[0]]);

        marker.setIcon(cssIcon).bindPopup(popup);

        clusterGroup.addLayer(marker);

        new EnhancedPin({
          propsData: {
            item: feature,
          },
        }).$mount('.icon-inner');

        marker.on('click', e => {
          setTimeout(() => {
            new EnhancedPopup({
              propsData: {
                item: feature,
              },
            }).$mount('.popup-inner');
          });
        });
      });

      this.map.addLayer(clusterGroup);
    },
  },
};
</script>

<style>
.cluster-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--primary);
  border-radius: 50%;
  box-shadow: 0 0 0 3px rgba(48, 72, 107, 0.3);
  color: var(--white);
  font-size: 1em;
  font-weight: bold;
}
</style>

У меня ошибка в консоли

[Vue warn]: Cannot find element: .icon-inner

потому что .icon-inner не существует в DOM.

Как я могу использовать компонент Vue в качестве маркера? Должно работать при масштабировании и перемещении карты.

1 Ответ

0 голосов
/ 15 июля 2019

Обычный "трюк" для использования компонентов Vue в карте Leaflet - просто визуализация их вне документа и передача результирующего $el HTMLElement для Leaflet для обработки:

const myIconVueEl = new EnhancedPin(myPinData).$mount().$el; // no selector to mount into

const myIcon = L.divIcon({
  html: myIconVueEl.outerHTML // directly pass an HTMLElement
});

const myPopupVueEl = new EnhancedPopup(myPopupData).$mount().$el;

const marker = L.marker(latLng, {
  icon: myIcon
}).bindPopup(myPopupVueEl);
...