Vue2-leaflet map not showing properly in BoostrapVue modal

假装没事ソ 提交于 2020-07-09 03:19:10

问题


Here's my problem - a Vue2 leaflet map does not render correctly in BootstrapVue modal.

Here's what it looks like visually (it should show just the ocean)

<template>
  <div>
    <b-modal size="lg" :visible="visible" @hidden="$emit('clear')" title="Event details">
      <div class="foobar1">
        <l-map :center="center" :zoom="13" ref="mymap">
          <l-tile-layer :url="url" :attribution="attribution"></l-tile-layer>
          <l-marker :lat-lng="center"></l-marker>
        </l-map>
      </div>

      <template slot="modal-footer">
        <b-btn variant="danger" @click="deleteEventLocal(event.id)">Delete</b-btn>
      </template>
    </b-modal>
  </div>
</template>

<script>
import * as moment from "moment";
import { LMap, LMarker, LTileLayer } from "vue2-leaflet";
import { deleteEvent } from "./api";
import "vue-weather-widget/dist/css/vue-weather-widget.css";
import VueWeatherWidget from "vue-weather-widget";

export default {
  data() {
    return {
      center: L.latLng(event.latitude, event.longitude),
      url: "http://{s}.tile.osm.org/{z}/{x}/{y}.png",
      attribution:
        '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
    };
  },
  props: {
    visible: {
      type: Boolean
    },
    event: {
      required: true,
      type: Object
    }
  },
  methods: {
    async deleteEventLocal(id) {
      await deleteEvent(id);
      this.$emit("refresh");
      this.$emit("clear");
    }
  },
  components: {
    weather: VueWeatherWidget,
    LMap,
    LMarker,
    LTileLayer
  }
};
</script>

As you can see there aren't any CSS rules that could make the map spill outside the modal as it does. Which is weird.

I'm kinda asking this question to answer it myself as I couldn't find a solution before.


回答1:


There were 3 issues because of which this was happening.

  1. First - I forgot to load the leaflet css into main.js - this is why the leaflet map was somehow outside the modal.
//main.js
import '@babel/polyfill';
import Vue from 'vue';
import './plugins/bootstrap-vue';
import App from './App.vue';
import router from './router';
import store from './store';
//above imports not important to this answer

import 'leaflet/dist/leaflet.css'; //<--------------add this line

Vue.config.productionTip = false;

new Vue({
  router,
  store,
  render: h => h(App),
}).$mount('#app');
  1. Now the map may disappear. Set a width and height on the l-map component's container. I used a class but you can use style="" etc.
<div class="foobar1"> <!-- <--- Add a class on l-map's container -->
  <l-map :center="center" :zoom="13">
    <l-tile-layer :url="url" :attribution="attribution"></l-tile-layer>
    <l-marker :lat-lng="center"></l-marker>
  </l-map>
</div>
<style lang="scss">
.foobar1 {
  width: 100%;
  height: 400px;
}
</style>
  1. Now your map will render within the modal but if you move the map's view, you'll see that leaflet does not download the maps' squares in time. You will see something like this:

To fix this, create an event handler on b-modal for the @shown event.

<b-modal
  @shown="modalShown"


  @hidden="$emit('clear')"
  size="lg"
  :visible="visible"
  title="Event details"
 >

I called mine modalShown.

Then, add a ref attribute to your l-map. I called mine mymap.

<l-map ref="mymap" :center="center" :zoom="13">
  <l-tile-layer :url="url" :attribution="attribution"></l-tile-layer>
  <l-marker :lat-lng="center"></l-marker>
</l-map>

Then create a modalShown method in the Vue methods for your view/component and call invalidateSize() inside. I don't know why it works. invalidateSize is part of native leaflet API (vue2leaflet is just a wrapper), and we're calling it in this method.

export default {
  data() {
   //some data here
  }

  methods: {
     modalShown() {
      setTimeout(() => {
        //mapObject is a property that is part of leaflet
        this.$refs.mymap.mapObject.invalidateSize(); 
      }, 100);
    }
  }
}

Now everything should be fine - the map should not spill outside the modal, the map should be visible (duh) and the map squares should be downloaded when they are within the map body.

Here's my full code, it contains some stuff specific to my app but overall it contains all of the code snippets above.



来源:https://stackoverflow.com/questions/56364129/vue2-leaflet-map-not-showing-properly-in-boostrapvue-modal

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!