Vue2-传单地图在 BoostrapVue 模态中未正确显示
Vue2-leaflet map not showing properly in BoostrapVue modal
这是我的问题 - 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 个。
1. 首先 - 我忘记将传单 css 加载到 main.js
- 这就是传单地图不知何故在模态之外的原因。
//src/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
new Vue({
router,
store,
render: h => h(App),
}).$mount('#app');
2. 现在地图可能会消失。在 l-map
组件的容器上设置宽度和高度。我使用了 class 但你可以使用 style="" 等
<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 { /* <--- class we added above */
width: 100%;
height: 400px;
}
</style>
3. 现在您的地图将在模式中呈现,但是如果您移动地图的视图,您会看到传单没有及时下载地图的方块。
你会看到这样的东西:
解决这个问题:
在 b-modal
上为 @shown
事件创建事件处理程序。
<b-modal
@shown="modalShown"
@hidden="$emit('clear')"
size="lg"
:visible="visible"
title="Event details"
>
我叫我的 modalShown
.
然后,将 ref
属性添加到您的 l-map
。我叫我的 mymap
.
<l-map :center="center" :zoom="13" ref="mymap"> <!-- ref attribute added to l-map -->
<l-tile-layer :url="url" :attribution="attribution"></l-tile-layer>
<l-marker :lat-lng="center"></l-marker>
</l-map>
然后,在 Vue 方法中为你的 view/component 创建一个 modalShown
方法,并在里面调用 invalidateSize()
。
export default {
data() {
//some data here
}
methods: {
modalShown() {
setTimeout(() => {
//mapObject is a property that is part of leaflet
this.$refs.mymap.mapObject.invalidateSize();
}, 100);
}
}
}
现在一切正常:
- 地图不应溢出模态
- 地图应该可见(呃)
- 地图正方形应在地图主体内下载
Artur Tagisow 回答的补充
如果您的地图位于子组件中,您也可以对父组件使用此方法。
export default {
data() {
//some data here
}
methods: {
modalShown() {
setTimeout(() => {
window.dispatchEvent(new Event("resize"));
}, 100);
}
}
}
对于 vue.js 和 nuxt.js 开发人员,可能是因为使用 v-show 或 v-if
!在你的情况下显示 none 发生在 bootstrap 模态
但别担心,你唯一需要做的就是使用仅客户端(它类似于 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 浏览器中加载,可能是因为 geolocation
这是我的问题 - 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 个。
1. 首先 - 我忘记将传单 css 加载到 main.js
- 这就是传单地图不知何故在模态之外的原因。
//src/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
new Vue({
router,
store,
render: h => h(App),
}).$mount('#app');
2. 现在地图可能会消失。在 l-map
组件的容器上设置宽度和高度。我使用了 class 但你可以使用 style="" 等
<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 { /* <--- class we added above */
width: 100%;
height: 400px;
}
</style>
3. 现在您的地图将在模式中呈现,但是如果您移动地图的视图,您会看到传单没有及时下载地图的方块。 你会看到这样的东西:
解决这个问题:
在
b-modal
上为@shown
事件创建事件处理程序。<b-modal @shown="modalShown" @hidden="$emit('clear')" size="lg" :visible="visible" title="Event details" >
我叫我的
modalShown
.然后,将
ref
属性添加到您的l-map
。我叫我的mymap
.<l-map :center="center" :zoom="13" ref="mymap"> <!-- ref attribute added to l-map --> <l-tile-layer :url="url" :attribution="attribution"></l-tile-layer> <l-marker :lat-lng="center"></l-marker> </l-map>
然后,在 Vue 方法中为你的 view/component 创建一个
modalShown
方法,并在里面调用invalidateSize()
。export default { data() { //some data here } methods: { modalShown() { setTimeout(() => { //mapObject is a property that is part of leaflet this.$refs.mymap.mapObject.invalidateSize(); }, 100); } } }
现在一切正常:
- 地图不应溢出模态
- 地图应该可见(呃)
- 地图正方形应在地图主体内下载
Artur Tagisow 回答的补充
如果您的地图位于子组件中,您也可以对父组件使用此方法。
export default {
data() {
//some data here
}
methods: {
modalShown() {
setTimeout(() => {
window.dispatchEvent(new Event("resize"));
}, 100);
}
}
}
对于 vue.js 和 nuxt.js 开发人员,可能是因为使用 v-show 或 v-if !在你的情况下显示 none 发生在 bootstrap 模态 但别担心,你唯一需要做的就是使用仅客户端(它类似于 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 浏览器中加载,可能是因为 geolocation