Карта Vue2-листовки не отображается должным образом в модальности BoostrapVue
Вот моя проблема - карта листовки Vue2 не отображается правильно в модале BootstrapVue.
Вот как это выглядит визуально (оно должно показывать только океан)
<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:
'© <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>
Как вы можете видеть, нет никаких правил CSS, которые могли бы заставить карту выплеснуться за пределы модальной, как это происходит. Что странно.
Я вроде задаю этот вопрос, чтобы ответить на него сам, так как я не мог найти решение раньше.
3 ответа
Было 3 проблемы, из-за которых это происходило.
- Во-первых - я забыл загрузить листовку CSS в
main.js
- поэтому карта листовки была как-то вне модальной.
//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');
- Теперь карта может исчезнуть. Установите ширину и высоту на
l-map
контейнер компонента.
<div class="foobar1">
<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>
- Теперь ваша карта будет отображаться в модальном режиме, но если вы переместите вид карты, вы увидите, что листовка не загружает квадраты карт во времени. Вы увидите что-то вроде этого:
Чтобы это исправить, создайте обработчик событий на b-modal
для @shown
событие.
<b-modal
size="lg"
:visible="visible"
@hidden="$emit('clear')"
title="Event details"
@shown="modalShown"
>
Я назвал мой modalShown
,
Затем добавьте ref
приписать к вашему l-map
, Я назвал мой mymap
,
<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>
Затем создайте modalShown
метод в методах Vue для вашего представления / компонента и вызова invalidateSize()
внутри. Я не знаю, почему это работает. invalidateSize
является частью нативного API листовки ( vue2leaflet - просто оболочка), и мы вызываем его в этом методе.
export default {
data() {
//some data here
}
methods: {
modalShown() {
setTimeout(() => {
this.$refs.mymap.mapObject.invalidateSize();
}, 100);
}
}
}
Теперь все должно быть хорошо - карта не должна выходить за пределы модальной, карта должна быть видимой (дух) и квадраты карты должны быть загружены, когда они находятся в теле карты.
Дополнительно к ответу Артура Тагисова
Вы также можете использовать этот подход к родительскому компоненту, если ваша карта находится в дочернем компоненте.
export default {
data() {
//some data here
}
methods: {
modalShown() {
setTimeout(() => {
window.dispatchEvent(new Event("resize"));
}, 100);
}
}
}
Для разработчиков vue.js и nuxt.js, возможно, это связано с использованием v-show или v-if! ssr, но для новой версии js-фреймворков, таких как nuxt или vue):
<client-only>
<div id="bootstrapModal">
<div id="map-wrap" style="height: 100vh">
<l-map :zoom=13 :center="[55.9464418,8.1277591]">
<l-tile-layer url="http://{s}.tile.osm.org/{z}/{x}/{y}.png"></l-tile-layer>
<l-marker :lat-lng="[55.9464418,8.1277591]"></l-marker>
</l-map>
</div>
</div>
</client-only>
ps: если все еще не загружается в браузерах iphone, это, вероятно, из-за геолокации