Problem with vue2-google-maps with custom marker and icon resize, misplaced on zoom out

1.3k views Asked by At

Vue.use(VueGoogleMaps, {
  load: {
    key: ''
  },
});

new Vue({
  el: '#root',
  computed:{
    icon(){
        if (this.resized)
            return {
            url:"https://i.ibb.co/bdykLz4/test.png",
            size: { width: 100, height: 100, f: "px", b: "px" },
            scaledSize: { width: 50, height: 50, f: "px", b: "px" }
                
            }
        else
            return {
            url:"https://i.ibb.co/bdykLz4/test.png"
            }
      
    }
  },
  data: {
    resized:true,
    startLocation: {
      lat: 38.7126659,
      lng: -9.3051496
    },
    coordinates: {
      0: {
        full_name: 'Point 1',
      lat: 38.7226659,
      lng: -9.3151496
      },
      1: {
        full_name: 'Point 2',
      lat: 38.7136659,
      lng: -9.3061496
      }
    },
  },
  methods: {
    getPosition: function(marker) {
      return {
        lat: parseFloat(marker.lat),
        lng: parseFloat(marker.lng)
      }
    },
  }
});
<script src="https://xkjyeah.github.io/vue-google-maps/vue-google-maps.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<body>
  <div id="root">
    <gmap-map ref="mymap" :center="startLocation" :zoom="14" style="width: 100%; height: 500px">

      <gmap-marker v-for="(item, key) in coordinates" :key="key" :position="getPosition(item)" :icon="icon"/>

    </gmap-map>
    Resized: <input type="checkbox" id="checkbox" v-model="resized" >
  </div>

</body>

I am trying to use custom markers with vue2-google-maps, and found a strange behaviour.

If I use a png image for example 100x100 pixels and set the properties to resize it to 50x50 pixels, when I start to zoom out, the marker start to move away from the coordinates.

If I did not use the resize property, there is no problem.

I have searched a lot about this issue and canĀ“t find anything.

I had prepared a JSFiddle, just uncheck the checkbox and everything is ok during the zoom out, but if you let the checkbox marked and start to zoom out, you will see that the mark goes to the ocean, when it should be on Portugal.

The difference on the object passed to the icon property is:

when checked:

{
   url:"https://i.ibb.co/bdykLz4/test.png",
   size: { width: 100, height: 100, f: "px", b: "px" },
   scaledSize: { width: 50, height: 50, f: "px", b: "px" }
}

when unchecked:

{
   url:"https://i.ibb.co/bdykLz4/test.png",
}

Here is the fiddle: https://jsfiddle.net/5dw83v7g/3/

UPDATE: If I keep "size" and "scaledSize" the same, the problem disapears

best regards,

TIA

1

There are 1 answers

6
Arash Yazdani On

Vue.use(VueGoogleMaps, {
  load: {
    key: 'YOUR_API_KEY'
  },
});

new Vue({
  el: '#root',
 computed:{
    icon(){
        if (this.resized)
            return {
            url:"https://i.ibb.co/bdykLz4/test.png",
            size: { width: 100, height: 100, f: "px", b: "px" },
            scaledSize: { width: 50, height: 50, f: "px", b: "px" }
                
            }
        else
            return {
            url:"https://i.ibb.co/bdykLz4/test.png"
            }
      
    }
    },
  data: {
    startLocation: {
      lat: 10.3157,
      lng: 123.8854
    },
    coordinates: {
      0: {
        full_name: 'Erich  Kunze',
        lat: '10.31',
        lng: '123.89'
      },
      1: {
        full_name: 'Delmer Olson',
        lat: '10.32',
        lng: '123.89'
      }
    },
    infoPosition: null,
    infoContent: null,
    infoOpened: false,
    infoCurrentKey: null,
    infoOptions: {
      pixelOffset: {
        width: 0,
        height: -35
      }
    },
  },
  methods: {
    getPosition: function(marker) {
      return {
        lat: parseFloat(marker.lat),
        lng: parseFloat(marker.lng)
      }
    },
    toggleInfo: function(marker, key) {
      this.infoPosition = this.getPosition(marker);
      this.infoContent = marker.full_name;
      if (this.infoCurrentKey == key) {
        this.infoOpened = !this.infoOpened;
      } else {
        this.infoOpened = true;
        this.infoCurrentKey = key;
      }
    }
  }
});
<script src="https://xkjyeah.github.io/vue-google-maps/vue-google-maps.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<body>
  <div id="root">
    <gmap-map ref="mymap" :center="startLocation" :zoom="14" style="width: 100%; height: 500px">

      <gmap-marker v-for="(item, key) in coordinates" :key="key" :position="getPosition(item)" :icon="icon"/>

    </gmap-map>
    Resized: <input type="checkbox" id="checkbox" v-model="resized" >
  </div>

</body>

You have to change your code like this:

Vue.use(VueGoogleMaps, {
  load: {
    key: 'YOUR_API_KEY'
  },
});

new Vue({
  el: '#root',
 computed:{
    icon(){
        if (this.resized)
            return {
            url:"https://i.ibb.co/bdykLz4/test.png",
            size: { width: 100, height: 100, f: "px", b: "px" },
            scaledSize: { width: 50, height: 50, f: "px", b: "px" }
                
            }
        else
            return {
            url:"https://i.ibb.co/bdykLz4/test.png"
            }
      
    }
    },
  data: {
    startLocation: {
      lat: 10.3157,
      lng: 123.8854
    },
    coordinates: {
      0: {
        full_name: 'Erich  Kunze',
        lat: '10.31',
        lng: '123.89'
      },
      1: {
        full_name: 'Delmer Olson',
        lat: '10.32',
        lng: '123.89'
      }
    },
    infoPosition: null,
    infoContent: null,
    infoOpened: false,
    infoCurrentKey: null,
    infoOptions: {
      pixelOffset: {
        width: 0,
        height: -35
      }
    },
  },
  methods: {
    getPosition: function(marker) {
      return {
        lat: parseFloat(marker.lat),
        lng: parseFloat(marker.lng)
      }
    },
    toggleInfo: function(marker, key) {
      this.infoPosition = this.getPosition(marker);
      this.infoContent = marker.full_name;
      if (this.infoCurrentKey == key) {
        this.infoOpened = !this.infoOpened;
      } else {
        this.infoOpened = true;
        this.infoCurrentKey = key;
      }
    }
  }
});

and use thisin your body:

<body>
  <div id="root">
    <gmap-map ref="mymap" :center="startLocation" :zoom="14" style="width: 100%; height: 300px">

      <gmap-info-window :options="infoOptions" :position="infoPosition" :opened="infoOpened" @closeclick="infoOpened=false">
        {{infoContent}}
      </gmap-info-window>

      <gmap-marker v-for="(item, key) in coordinates" :key="key" :position="getPosition(item)" :icon="icon"/>

    </gmap-map>
  </div>

</body>

I used this code here.

Vue.use(VueGoogleMaps, {
  load: {
    key: 'YOUR_API_KEY'
  },
});

new Vue({
  el: '#root',
 computed:{
    icon(){
        if (this.resized)
            return {
            url:"https://i.ibb.co/bdykLz4/test.png",
            size: { width: 100, height: 100, f: "px", b: "px" },
            scaledSize: { width: 50, height: 50, f: "px", b: "px" }
                
            }
        else
            return {
            url:"https://i.ibb.co/bdykLz4/test.png"
            }
      
    }
    },
  data: {
    startLocation: {
      lat: 10.3157,
      lng: 123.8854
    },
    coordinates: {
      0: {
        full_name: 'Erich  Kunze',
        lat: '10.31',
        lng: '123.89'
      },
      1: {
        full_name: 'Delmer Olson',
        lat: '10.32',
        lng: '123.89'
      }
    },
    infoPosition: null,
    infoContent: null,
    infoOpened: false,
    infoCurrentKey: null,
    infoOptions: {
      pixelOffset: {
        width: 0,
        height: -35
      }
    },
  },
  methods: {
    getPosition: function(marker) {
      return {
        lat: parseFloat(marker.lat),
        lng: parseFloat(marker.lng)
      }
    },
    toggleInfo: function(marker, key) {
      this.infoPosition = this.getPosition(marker);
      this.infoContent = marker.full_name;
      if (this.infoCurrentKey == key) {
        this.infoOpened = !this.infoOpened;
      } else {
        this.infoOpened = true;
        this.infoCurrentKey = key;
      }
    }
  }
});
<script src="https://xkjyeah.github.io/vue-google-maps/vue-google-maps.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<body>
  <div id="root">
    <gmap-map ref="mymap" :center="startLocation" :zoom="14" style="width: 100%; height: 500px">

      <gmap-marker v-for="(item, key) in coordinates" :key="key" :position="getPosition(item)" :icon="icon"/>

    </gmap-map>
    Resized: <input type="checkbox" id="checkbox" v-model="resized" >
  </div>

</body>

Please rate me if it was helpful. Thanks a lot.