Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vue-marker not displaying on map and map not fully rendering #96

Closed
4 tasks
qualisign opened this issue Nov 1, 2017 · 47 comments
Closed
4 tasks

vue-marker not displaying on map and map not fully rendering #96

qualisign opened this issue Nov 1, 2017 · 47 comments
Labels
Docs Issue related to wrong / missing docs help wanted wontfix

Comments

@qualisign
Copy link

qualisign commented Nov 1, 2017

Description

Steps to Reproduce

  1. installed Vue2Leaflet via npm
  2. created a component called Simple with the following contents (just copied the Simple.vue example and added the style import)

<template>
  <div class="simple">
    <div id="top_div" style="height: 100%">
      <v-map :zoom="zoom" :center="center" style="height: 1000px; width: 1000px">
        <v-tilelayer :url="url" :attribution="attribution"></v-tilelayer>
        <v-marker :lat-lng="marker"></v-marker>       
      </v-map>
    </div>
  </div>
</template>

<script>
 import Vue2Leaflet from 'vue2-leaflet';
 
export default {
  name: 'simple',
  components: {
    'v-map': Vue2Leaflet.Map,
    'v-tilelayer' :Vue2Leaflet.TileLayer,
    'v-marker': Vue2Leaflet.Marker
  },
  data () {
    return {
        zoom: 13,
        center: [47.413220, -1.219482],
        url: 'http://{s}.tile.osm.org/{z}/{x}/{y}.png',
        attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
        marker: L.latLng(47.413220, -1.219482),
    }
  }
}
</script>

<style>
 @import "~leaflet/dist/leaflet.css";
</style>

Expected Results

I expect to see the basic map with marker from the example jsfiddle.

Actual Results

The map appears as a large gray box with a small section with rendered map tiles. My problem looks identical to the one described in #81 , but I do include the leaflet css import.

leaflet

What is strange is that when I resize the window, the map loads as it should, but the marker does not show up. I see in the html that the marker is loaded, however:
leaflet2

Browsers Affected

  • [x ] Chrome
  • [x ] Firefox
  • Edge
  • Safari 9
  • Safari 8
  • IE 11

Versions

  • Leaflet: v1.2.0
  • Vue: v2.5.2
  • Vue2Leaflet: v0.0.55
@azurelogic
Copy link

I've had some similar issues. The marker image issue I solved using info from these threads:
PaulLeCam/react-leaflet#255
Leaflet/Leaflet#4849
Leaflet/Leaflet#4968

Basically, sounds like webpack is jacking up the embedded image URLs in the CSS. Throwing this at the top of your main.js may help:

import L from 'leaflet';
delete L.Icon.Default.prototype._getIconUrl;

L.Icon.Default.mergeOptions({
  iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'),
  iconUrl: require('leaflet/dist/images/marker-icon.png'),
  shadowUrl: require('leaflet/dist/images/marker-shadow.png')
});

I've gotten to the point that everything renders after the user resizes but I can't figure out why I'm getting grey space before that...

@azurelogic
Copy link

I ended up with a hack that helped get everything to render correctly as far as the resize issue goes.

mounted() {
      setTimeout(function() { window.dispatchEvent(new Event('resize')) }, 250);
}

This works down to 200 ms. After that the hack fails. Seems to be some sort of race condition. I tested slower bandwidths and they work fine.

@qualisign
Copy link
Author

@azurelogic

Both those suggestions worked, thanks for the help.

@KoRiGaN
Copy link
Collaborator

KoRiGaN commented Nov 7, 2017

Hi @qualisign,

The icon issue is well known. Leaflet and Webpack don't play well together. You can see the issue #28 and the pull request in Leaflet to fix this.
@azurelogic give the right way to fix this issue in the meantime.

The other issue is the map tiles not loading properly.
@azurelogic seems right to force the view to be redrawn.
I can't reproduce and I would like to know how you reproduce it.
How do you set your map container size?
If you resize the map container manually, you need to call map.invalidateSize().

Mickaël

@azurelogic
Copy link

The problem for me is that I'm using it along with Vuetity, which includes flexbox-based grid components. I have some tricks to size it as a square, but even before I added that on top I was having issues. I wish I had a simple example to illustrate.

@KoRiGaN
Copy link
Collaborator

KoRiGaN commented Nov 13, 2017

Never experienced any issue like this on my tests.
It seems to me that this issue is a problem between Leaflet and flexbox based sizing.
I should add this hack into a tips and tricks section in the Readme.

What do you think?

Micka

@vue-leaflet vue-leaflet deleted a comment from shaief Nov 14, 2017
@vue-leaflet vue-leaflet deleted a comment from shaief Nov 14, 2017
@vue-leaflet vue-leaflet deleted a comment from shaief Nov 14, 2017
@azurelogic
Copy link

Can't hurt to suggest it. Like I said though, I'm using it inside of flexbox. On top of that, I'm binding the height of the map or its container to another property that's computed from the width of a column and stuff. Can't say that everything I'm doing is a good idea, but the whole site is pretty responsive. That's the difficulty with Leaflet to begin with though, it seems.

@gkatsanos
Copy link

Same problem here. Vuetify / Flexbox + gray area showing up.

@KoRiGaN
Copy link
Collaborator

KoRiGaN commented Dec 14, 2017

I gave a try to Vuetify / Flexbox.

I started a Vue project added Vuetify and used this layout.
I added Vue2Leaflet and created a map component.
Added this map component in the main area of the baseline layout and leaflet CSS as a script tag in the index.html file.
Works fine.

The issue is that if the map container size change Leaflet doesn't know about it and doesn't load tiles to cover the new size of the container.
It appends in my test when closing the left menu, the maps get bigger a part of the map is now displayed on the right-hand side but no tile is displayed => grey area.

I'm not sure what your issue is as I can't really reproduce it but I think your map container is initialized with a small size(0px ?). The size is increased later but the map doesn't adapt like in my issue so you end up having a mostly grey area.

How to fix it :
The tricky part is to detect when the size change, the only two options I found are:

  • Wait for Resize Observer to be implemented in browsers and use it. At the moment no current version of browser implements it. It will work with Chrome 64.
  • Use a library called CSS Element Queries to detect changes using the ResizeSensor JS Class, debounce the events, and use Leaflet invalidateSize to force leaflet to adapt to the current size.

The second seems to be the only viable choice.

What do you guys think?

@brandon-dev-aleriola
Copy link

brandon-dev-aleriola commented Mar 6, 2018

In the console if you type:

$('img.leaflet-marker-icon.leaflet-zoom-animated.leaflet-interactive').src

you might get something like this :

"data:image/png;base64,iVBORw0K[ ...................]UVORK5CYII=")marker-icon-2x.png"

you will notice that the extra double quotes are screwing up the get request.
try going into the DOM and removing this porting of the string and see if a marker appears.

")marker-icon-2x.png

leave the last double quote

@brandon-dev-aleriola
Copy link

As for the issue with sizing issue in Vuetify:
add a class on top of the v-container element :

.i {
height: 100%;
margin: 0;
padding: 0;
width: 100%;
z-index: 0;
}

then go into the vuetify.css and rip out all of the media queries for the .container class. I think its on lines 9301 to 9313.

@ghost
Copy link

ghost commented Mar 23, 2018

Apologies for the question, but where in the file system do I put the "leaflet.css" to include it with
@import "~leaflet/dist/leaflet.css";

I've copied leaflet.css all over my disk, to no avail, and found no documentation of @import and were webpack looks for stuff.

@brandon-dev-aleriola
Copy link

brandon-dev-aleriola commented Mar 24, 2018

It should be added in your ~/projectName/src/main.js file when you instantiate your Vue object.
I'm also using Vuetify but my main.js file looks like this:

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import Vuetify from 'vuetify'
import 'vuetify/dist/vuetify.css'
import "leaflet/dist/leaflet.css"
import "vue-d3-network/dist/vue-d3-network.css"




Vue.use(Vuetify, { theme: {
  primary: '#FF6E40',
  secondary: '#FF9E80',
  accent: '#26A69A',
  error: '#FF3D00',
  warning: '#EA80FC',
  info: '#29B6F6',
  success: '#64DD17'
}})

Vue.config.productionTip = false


new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
})

@ghost
Copy link

ghost commented Mar 25, 2018

Many thanks, so simple ...

@Phyks
Copy link

Phyks commented Jun 8, 2018

Hi,

I'm having similar issues as @azurelogic (Vuetify and flexbox rendering here, map is not rendered completely until a resize event).

I tried the #96 (comment) solution, but it does not work in my case as my component is mounted when the map object is created (but not necessarily rendered yet). Then, the timeout is not working and it seems super hacky to make it work.

I tried with the load event on the map, without any luck so far (the event does not seem to be triggered actually… :/).

Did anyone manage to find a working solution for this issue? Thanks!

@DonNicoJs
Copy link
Member

@Phyks if you check the code coming from this pr: #200 you will see that I added an event called: load
that you can listen to with @load on the l-map component.

You will need to use the code from my fork to have it for now

@chriscdn
Copy link

chriscdn commented Aug 7, 2018

@BrandonDevaleriola I'm having this double quote problem, which is causing the GET request to fail. Is there a workaround or did I somehow miss it in your response?

@duebbert
Copy link

I've had an issue with the grey area too (also using Vuetify). But I noticed that the issue went away if I change the zoom. So, a very dirty trick that I'm doing is that I programmatically zoom in and out again when the map loads. Then all seems to be fine and it's so fast that it's barely noticeable... not a nice workaround though I admit but none of the other suggestions here helped.

@nparley
Copy link
Contributor

nparley commented Oct 11, 2018

For anyone having problems with vuetify this is the layout which is working for me:

<v-container class="pa-0" fluid fill-height>
        <v-layout>
            <v-flex x12>
                <l-map v-resize="onResize">
                </l-map>
            </v-flex>
        </v-layout>
</v-container>

And on resize I do:

onResize() {
    this.$refs.map.mapObject.invalidateSize();
}

@Alhakem
Copy link

Alhakem commented Nov 6, 2018

Hello guys, If you are facing such problem with vuetifyjs it's most probably that the map container is initialized with a small size.

To solve this problem you need to insure that you are loading the map whenever the container is taking the actual size.

For example, if you are using dialog as a container for the map, all what you have to do is using 'lazy' prop to insure that the content is rendered on mounted; in other words, the map must be rendered only if the dialog is activated 🎉

<v-dialog v-model="dialog" lazy>
    <l-map
      :zoom="zoom"
      :center="center"
      :style="mapStyle"
      @update:center="centerUpdate"
      @update:zoom="zoomUpdate">
      <l-tile-layer
        :url="url"
        :attribution="attribution"/>
      <l-marker :lat-lng="marker">
      </l-marker>
    </l-map>
</v-dialog>

I hope this will help some one 😄

@tiangolo
Copy link

tiangolo commented Jan 6, 2019

Building for production, what worked for me was:

import 'leaflet/dist/leaflet.css';
import * as L from 'leaflet';
import * as vl from 'vue2-leaflet';
delete (vl as any).L.Icon.Default.prototype._getIconUrl;
(vl as any).L.Icon.Default.mergeOptions({
  iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'),
  iconUrl: require('leaflet/dist/images/marker-icon.png'),
  shadowUrl: require('leaflet/dist/images/marker-shadow.png'),
});

I'm using TypeScript. And strangely enough, my editor complains that "vue2-leaflet has no exported member L". But still, doing it that way the workaround works.

It's also necessary to have import * as L from 'leaflet';.


Edit: The workaround I was using was working only for local development with Vue CLI. But didn't work while building for prod.

It's working properly for me, after a couple configurations:

For the icons not showing up when using Webpack, there's now a plug-in to solve it at the Leaflet level: https://github.com/ghybs/leaflet-defaulticon-compatibility

My main.ts looks now like:

import '@babel/polyfill';
// Import Component hooks before component definitions
import './component-hooks';
import Vue from 'vue';
import './plugins/vuetify';
import './plugins/vee-validate';
import App from './App.vue';
import router from './router';
import store from '@/store';
import './registerServiceWorker';
import 'vuetify/dist/vuetify.min.css';
import 'leaflet/dist/leaflet.css';
// Re-uses images from ~leaflet package
import 'leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.webpack.css';
import * as L from 'leaflet';
import 'leaflet-defaulticon-compatibility';

Vue.config.productionTip = false;

new Vue({
  router,
  store,
  render: (h) => h(App),
}).$mount('#app');

I'm using Vuetify. And I was having a gray area under the map, but I wasn't setting the zoom (my error). After setting a zoom higher than the default, the whole map region has rendered tiles properly.

The relevant section in my .vue file now looks like:

<v-responsive :aspect-ratio="16/9">
  <LMap @click="onMapClick"
    :zoom="5"
  >
    <LTileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"></LTileLayer>
    <LMarker v-if="point" :lat-lng="point"></LMarker>
  </LMap>
</v-responsive>

And then in the script, as part of the component:

  public onMapClick(e) {
    this.latitude = e.latlng.lat;
    this.longitude = e.latlng.lng;
  }

  get point() {
    if (this.latitude !== null && this.longitude !== null) {
      return {lat: this.latitude, lng: this.longitude};
    }
  }

I'm using TypeScript, but the plug-ins and configurations should work the same for normal JavaScript.

@r3j3c73d
Copy link

r3j3c73d commented Jan 9, 2019

Hi, I was done all stuff that guys said on top, but when I want to use lmap component in v-card of vuetify it disappears. What should i do to fix this? any suggestion?

###Sulotion
I resolve this problem by writing a div tag around lmap and give 100% width and 500px (customizable) height for style

@waleedshkt
Copy link

Btw, I am using iView UI Library

I was experiencing the same issue of leaflet tile not fully loading on the map.
After going through various solutions and hacks suggested above., I finally managed to solve the issue by calling: this.$refs.map.mapObject.invalideSize() inside mounted lifecycle hook.
Plus I set a hard-coded height and width of the map's parent container <div>.
And lastly, added the following code inside main.js file

(this step is though added in docs of vue2-leaflet when going through the installing section)

import { L } from 'vue2-leaflet';
delete L.Icon.Default.prototype._getIconUrl;

L.Icon.Default.mergeOptions({
  iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'),
  iconUrl: require('leaflet/dist/images/marker-icon.png'),
  shadowUrl: require('leaflet/dist/images/marker-shadow.png')
});```

@kaboume
Copy link

kaboume commented Mar 7, 2019

I have the same problem (Nuxt + Vuetify).
The solution of Alhakem works a little (add the "lazy" paramater) in the <v-bottom-sheet or v-dialog)
Ex

<v-bottom-sheet v-model="sheetMap" full-width lazy>

This works at the first display of the v-bottom-sheet. But, after resizing the browser window and clicking on the button to show the v-bottom-sheet : only a part of the map is displayed..

In another page of the web site, I have a map in a tab panel (https://vuetifyjs.com/en/components/tabs) and I have the same issue : only a part ok the map is displayed.

IF you have an universal solution...

@Alhakem
Copy link

Alhakem commented Mar 7, 2019

Hi @kaboume ,

This works at the first display of the v-bottom-sheet. But, after resizing the browser window and clicking on the button to show the v-bottom-sheet : only a part of the map is displayed.

As I mentioned above this issue happens because the changes in the container dimensions. However, I recommend you to overcome this issue by force Vue to re-render JUST the map component whenever the button is clicked to show the v-bottom-sheet

Keep in mind that if you find yourself needing to force re-rendering any component, maybe you aren't doing something the right way.

In another page of the web site, I have a map in a tab panel (https://vuetifyjs.com/en/components/tabs) and I have the same issue : only a part ok the map is displayed.

You can solve this the same way by using 'lazy' prop in v-tab-item tag

@kaboume
Copy link

kaboume commented Mar 7, 2019

Hi @Alhakem ,
Thank you for the v-tab-item tag! I did not see that we could also use the "lazy" parameter in the v-tab!

Fot the sheet, the solution to rerender the Map works great!!! (I used the solution described at the bottom of this page : http://michaelnthiessen.com/force-re-render/).

I setted a key parameter on the map

<l-map :key="componentKey" ref="refMap" :zoom="10" :center="positionInitiale">

and change the value of the componentKey after cliquing on the button to display the sheet

forceRerender() {
      this.componentKey = this.componentKey + 1;
    },
watch: {
    sheetMap: function(val) {
      if (val == true) {
        this.$nextTick(() => {
          this.$refs.refMap2.forceRerender();
        });
      }
    }
  },

Big thanks to all!

@Alhakem
Copy link

Alhakem commented Mar 9, 2019

@kaboume well done 😊👍

@DonNicoJs
Copy link
Member

Is anyone in this thread up to write down in the docs some guidelines that are scattered here? It would be helpful for the next people with the same problems

@DonNicoJs DonNicoJs added help wanted Docs Issue related to wrong / missing docs labels Apr 21, 2019
@Alhakem
Copy link

Alhakem commented Apr 21, 2019

@DonNicoJs

I can help with that

@DonNicoJs
Copy link
Member

@Alhakem Thanks! Waiting for a docs PR so :)

@0x8f701
Copy link

0x8f701 commented Jun 1, 2019

Screenshot from 2019-06-01 13-24-18

this is absolutely crazy!~...............................when it happens, it can cause my others vue components being blank like this..........

@0x8f701
Copy link

0x8f701 commented Jun 2, 2019

peekUXXZ2Z

@0x8f701
Copy link

0x8f701 commented Jun 2, 2019

When I resize it restores, can someone help me?

@DonNicoJs
Copy link
Member

@GopherJ are you using vuetify ? have you read and tried the solution posted in this issue ?

@0x8f701
Copy link

0x8f701 commented Jun 3, 2019

@DonNicoJs No, I'm not using vuetify. Why when I change tab it influences the map? By the way I'm using keep-alive for router

@kaboume
Copy link

kaboume commented Jun 5, 2019

Hi @Alhakem ,
Thank you for the v-tab-item tag! I did not see that we could also use the "lazy" parameter in the v-tab!

Fot the sheet, the solution to rerender the Map works great!!! (I used the solution described at the bottom of this page : http://michaelnthiessen.com/force-re-render/).

I setted a key parameter on the map

<l-map :key="componentKey" ref="refMap" :zoom="10" :center="positionInitiale">

and change the value of the componentKey after cliquing on the button to display the sheet

forceRerender() {
      this.componentKey = this.componentKey + 1;
    },
watch: {
    sheetMap: function(val) {
      if (val == true) {
        this.$nextTick(() => {
          this.$refs.refMap2.forceRerender();
        });
      }
    }
  },

Big thanks to all!

Hi,
There is a disadvantage to using the lazy property in the v-tab-item tag : SEO ! With a nuxt project in universal mode, the content of the v-tab-item is not created by the server side : when displaying the page soutce, the tab item is empty :( So, it's not the best solution when we have to optimize the SEO of the page.

@kaboume
Copy link

kaboume commented Jun 28, 2019

Hi,
In order to work with SEO, I added a watch function when tab item is selected :

watch: {
    tabSelected: function(tabItem) {
      // Refresh the map of the tab
      this.$nextTick(() => {
        if (this.$refs.refCarteEtablissements) {
          this.$refs.refCarteEtablissements.map(ref => {
            ref.forceRerender();
          });
        }
      });
    }
  },

And I my CarteEtablissement component

<l-map
        :zoom="13"
        :center="positionInitiale"
        :key="componentKey"
        style="z-index:1"
      >
....
</l-map>
 data() {
    return {
       ....
      componentKey: 0,
      ...
    };
  },
 methods: {
    forceRerender() {
      this.componentKey = this.componentKey + 1;
    },
}

And now the map displays correctly and when I show the source of the page, I see the text for the SEO.

@NewRanger
Copy link

I am so sorry, is there any way to use local set of tiles? from assets folder for example. I can't figure out how to define {z}/{x}/{y} path to local tile set folder.

@stale
Copy link

stale bot commented Jan 1, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Jan 1, 2020
@stale stale bot closed this as completed Jan 8, 2020
@dstearle
Copy link

dstearle commented Feb 27, 2020

Posting this here since it seems related. When viewing the examples for custom icons one vue2-leaflet's docs the re-sizable baseball icon that uses an l-icon tag strangley does not work in the provided code on the docs and jsfiddle (https://codesandbox.io/s/51sx6) although it does on the example in the docs itself (https://vue2-leaflet.netlify.com/examples/custom-icons.html). I found a fix for this by simply binding icon-url to a data property that uses require("yourImageDirectoryGoesHere").

Another thing to note is that I am also using the solution posted by @azurelogic in the main.js.

@DonNicoJs
Copy link
Member

@dstearle Could you open a new issue to fix the docs? It would be greatly appreciated

@teleyinex
Copy link

Quick update for those using vuetify 2.0. The lazy prop does not longer work, but v-lazy works:

v-lazy
  l-map

That will do the trick!

@iboates
Copy link

iboates commented Feb 24, 2021

I have a situation where my <l-map> component is inside a Vuetify stepper, and the problem is that it renders all of the <v-stepper-content> components at once, but then not the map. I'm not that experienced with Vue so maybe this is totally wrong, but it seems to be that the map is pre-initizalied at too-small a size and then when you step to the one with the map, it doesn't load properly and you get the grey square with the map tiles bunched up in the upper-left-hand corner.

I tried many solutions here but the only one I could get to work was to set a watcher on the variable controlling the stepper and use @azurelogic's setTimeout-based solution if the stepper variable is the one with the map on it, like this:

Template

<v-stepper v-model="stepper">
    <v-stepper-items>
      <v-stepper-content step="1">
        <v-card-actions>
          <v-spacer></v-spacer>
          <v-btn color="primary" @click.native="stepper = 2">Continue</v-btn>
        </v-card-actions>
      </v-stepper-content>
      <v-stepper-content step="2">
            <client-only>
              <l-map id="map" ref="map">
                <l-tile-layer
                  :url="mapInitData.basemap.url"
                  :attribution="mapInitData.basemap.attribution"
                />
              </l-map>
            </client-only>
      </v-stepper-content>
    </v-stepper-items>
  </v-stepper>

Script

import ClientOnly from "vue-client-only";
import { LMap, LTileLayer, LGeoJson } from "vue2-leaflet";
import { Icon } from "leaflet";
delete Icon.Default.prototype._getIconUrl;
Icon.Default.mergeOptions({
  iconRetinaUrl: require("leaflet/dist/images/marker-icon-2x.png"),
  iconUrl: require("@/assets/marker-icon.png"),
  shadowUrl: require("leaflet/dist/images/marker-shadow.png")
});

export default {
  components: {
    LMap,
    LTileLayer,
    ClientOnly
  },
  data() {
    return {
      stepper: 1,
      mapInitData: {
        basemap: {
          attribution:
            '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
          url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        }
      },
      
  watch: {
    stepper: function (val) {
      if (val === 2) {
        this.reloadMap();
      }
    }
  },
  methods: {
    reloadMap: function() {
      console.log("reloading map");
      // this.$refs.map.mapObject.invalidateSize(); // Doesn't work!
      setTimeout(function() { window.dispatchEvent(new Event('resize')) }, 250);
    }
  }
};

a18jimol added a commit to a18jimol/Examensarbete that referenced this issue Apr 25, 2021
Marker fix for Leaflet in Vue.js, code by azurelogic (2017) vue-leaflet/Vue2Leaflet#96 [Accessed 2021-04-25]
This code is needed so the URL for the markers are retrieved from the right location.
@AlanGreyjoy
Copy link

Quick update for those using vuetify 2.0. The lazy prop does not longer work, but v-lazy works:

v-lazy
  l-map

That will do the trick!

This guy right here! pin this somewhere!

@FuriosoJack
Copy link

Tengo una situación en la que mi <l-map>componente está dentro de un motor paso a paso de Vuetify, y el problema es que procesa todos los <v-stepper-content>componentes a la vez, pero no el mapa. No tengo tanta experiencia con Vue, así que tal vez esto esté totalmente mal, pero parece ser que el mapa está preiniciado en un tamaño demasiado pequeño y luego, cuando te acercas al que tiene el mapa, no se carga. correctamente y obtendrá el cuadrado gris con los mosaicos del mapa agrupados en la esquina superior izquierda.

Probé muchas soluciones aquí, pero la única que pude ponerme a trabajar fue establecer un observador en la variable que controla el paso a paso y usar la solución basada en @azurelogicsetTimeout si la variable paso a paso es la que tiene el mapa, así:

Modelo

<v-stepper v-model="stepper">
    <v-stepper-items>
      <v-stepper-content step="1">
        <v-card-actions>
          <v-spacer></v-spacer>
          <v-btn color="primary" @click.native="stepper = 2">Continue</v-btn>
        </v-card-actions>
      </v-stepper-content>
      <v-stepper-content step="2">
            <client-only>
              <l-map id="map" ref="map">
                <l-tile-layer
                  :url="mapInitData.basemap.url"
                  :attribution="mapInitData.basemap.attribution"
                />
              </l-map>
            </client-only>
      </v-stepper-content>
    </v-stepper-items>
  </v-stepper>

Texto

import ClientOnly from "vue-client-only";
import { LMap, LTileLayer, LGeoJson } from "vue2-leaflet";
import { Icon } from "leaflet";
delete Icon.Default.prototype._getIconUrl;
Icon.Default.mergeOptions({
  iconRetinaUrl: require("leaflet/dist/images/marker-icon-2x.png"),
  iconUrl: require("@/assets/marker-icon.png"),
  shadowUrl: require("leaflet/dist/images/marker-shadow.png")
});

export default {
  components: {
    LMap,
    LTileLayer,
    ClientOnly
  },
  data() {
    return {
      stepper: 1,
      mapInitData: {
        basemap: {
          attribution:
            '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
          url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        }
      },
      
  watch: {
    stepper: function (val) {
      if (val === 2) {
        this.reloadMap();
      }
    }
  },
  methods: {
    reloadMap: function() {
      console.log("reloading map");
      // this.$refs.map.mapObject.invalidateSize(); // Doesn't work!
      setTimeout(function() { window.dispatchEvent(new Event('resize')) }, 250);
    }
  }
};

Efectivamente this.$refs.map.mapObject.invalidateSize() no funciona y eso que los tengo en shadodom pero el setTimeOutSiFunciono

@pnavarretec01
Copy link

I ended up with a hack that helped get everything to render correctly as far as the resize issue goes.

mounted() {
      setTimeout(function() { window.dispatchEvent(new Event('resize')) }, 250);
}

This works down to 200 ms. After that the hack fails. Seems to be some sort of race condition. I tested slower bandwidths and they work fine.

This work for me!! thanks!!

@antoinegilles
Copy link

I ended up with a hack that helped get everything to render correctly as far as the resize issue goes.

mounted() {
      setTimeout(function() { window.dispatchEvent(new Event('resize')) }, 250);
}

This works down to 200 ms. After that the hack fails. Seems to be some sort of race condition. I tested slower bandwidths and they work fine.

thanks, it works, but I don't know if it's the cleanest solution :/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Docs Issue related to wrong / missing docs help wanted wontfix
Projects
None yet
Development

No branches or pull requests