programing

Vue2 리플릿 맵이 BoostrapVue 모달에 올바르게 표시되지 않음

goodcopy 2022. 7. 3. 23:12
반응형

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:
        '&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>

보시다시피 맵을 모달 외부로 유출시킬 수 있는 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컴포넌트의 컨테이너.저는 클래스를 사용했지만 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. 이제 지도는 모달 내에서 렌더링되지만 지도 뷰를 이동하면 지도의 사각형이 제때 다운로드되지 않는다는 것을 알 수 있습니다.다음과 같은 것이 표시됩니다.

css를 수정한 후 invalidate Size() 수정을 하지 않은 모달

이 문제를 해결하려면:

  • 이벤트 핸들러를 작성하다b-modal를 위해@shown이벤트입니다.

     <b-modal
       @shown="modalShown"
    
    
       @hidden="$emit('clear')"
       size="lg"
       :visible="visible"
       title="Event details"
     >
    

    나는 내 것을 불렀다.modalShown.

  • 다음으로 a를 추가합니다.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>
    
  • 그런 다음 다음,modalShown뷰/컴포넌트 및 호출에 대한 Vue 메서드의 메서드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);
        }
      }
    }
    

이제 모든 것이 정상입니다.

  • 지도는 모달 외부로 유출되지 않아야 합니다.
  • 맵이 표시되어야 합니다(duh).
  • 지도 본문 내에서 지도 정사각형을 다운로드해야 합니다.

여기 제 풀코드가 있습니다.제 앱에 특유한 내용이 포함되어 있지만 전체적으로 위의 코드 스니펫이 모두 포함되어 있습니다.

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를 사용하는 것이 원인일 수 있습니다. 단, 부트스트랩 모달에 의해 아무 일도 발생하지 않지만 걱정하지 말고 클라이언트 전용(sr와 같이 sr와 같이 nuxt 또는 vue와 같은 새 버전의 js 프레임워크)을 사용해야 합니다.

<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 브라우저에 아직 로딩되지 않은 경우 지리 위치 때문일 수 있습니다.

언급URL : https://stackoverflow.com/questions/56364129/vue2-leaflet-map-not-showing-properly-in-boostrapvue-modal

반응형