I’m using google maps javascript to render custom markers on my map, right now all my markers appear to be floating on the wrong positions, all of them aligned on a vertical line, one below another (check image), I don’t know what is happening and tried with chatgpt to fix but no luck.
When I move around on the map the markers are moved to the same position on the screen so they are always floating on the middle of the screen…
Image: https://i.imgur.com/INxOcj9.png
My vue.js component :
<template>
<div style="width:100%; height:100vh; display:flex; align-items:center; justify-content:center; position:relative; overflow:hidden;">
<div v-if="!googleMapsLoaded" style="width:100%; height:100%; display:flex; align-items:center; justify-content:center; position:absolute; top:0px; left:0px; overflow:hidden;">
<i class="fas fa-circle-notch fa-pulse fs_bigger c_secondary" style="margin:0px 0px 0px 0px;"></i>
</div>
<div :id="id" class="GOOGLEmap1"></div>
</div>
</template>
<script>
export default {
name: 'GoogleMap1',
data() {
return {
map: null,
googleMapsLoaded: false,
markers: [], // Store custom markers
mapInteracted: false, // Flag to track user interaction
};
},
props: {
id: { default: 'map', type: String },
places: { type: Array, required: true }
},
mounted() {
console.log(this.$options.name + ' component successfully mounted');
this.initMap();
},
watch: {
places: {
deep: true,
handler(newPlaces) {
if (!this.googleMapsLoaded) return;
this.clearMarkers();
// Only fitBounds if the user has not interacted with the map yet
if (!this.mapInteracted) {
this.fitBounds();
}
newPlaces.forEach(place => {
this.createCustomMarker(place);
});
}
}
},
methods: {
// Check if the map is fully loaded
checkMapLoaded() {
google.maps.event.addListener(this.map, 'tilesloaded', () => {
this.googleMapsLoaded = true;
console.log('Google Maps loaded successfully');
// Add markers once map is ready and fit the map bounds
this.places.forEach(place => {
this.createCustomMarker(place);
});
if (!this.mapInteracted) {
this.fitBounds();
}
});
},
// Initialize the map with options
initMap() {
const myOptions = {
zoom: 15,
center: new google.maps.LatLng(this.places[0].coordinates.lat, this.places[0].coordinates.lng),
streetViewControl: false,
mapTypeControl: false,
scaleControl: false,
zoomControl: true // Keep zoom control for better UX
};
this.map = new google.maps.Map(document.getElementById(this.id), myOptions);
// Detect user interaction with the map (pan or zoom)
google.maps.event.addListener(this.map, 'bounds_changed', () => {
this.mapInteracted = true; // Once user moves/zooms, stop calling fitBounds
});
this.checkMapLoaded(); // Check if the map is loaded before adding markers
},
// Create custom markers with your specified layout
createCustomMarker(place) {
if (!this.googleMapsLoaded) {
console.log('Google Maps is not yet loaded. Cannot add markers.');
return;
}
const position = new google.maps.LatLng(place.coordinates.lat, place.coordinates.lng);
// Create the HTML content for the custom marker
const markerContent = document.createElement('div');
markerContent.innerHTML = `
<div class="shadow" style="width:95px; height:95px; border-radius:50%; border:2px solid white; display:flex; align-items:center; justify-content:center; position:relative;">
<div style="background-image:url('${place.images[0]}'); width:90px; border:2px solid white; height:90px; border-radius:50%; display:flex; align-items:center; justify-content:center; position:relative; background-size:cover; background-position:center;"></div>
<div class="bc_secondary" style="width:30px; height:30px; display:flex; align-items:center; justify-content:center; position:absolute; bottom:-5px; right:-5px; border-radius:50%;">
<span class="fs_normal semi_bold c_light">${place.id}</span>
</div>
</div>
`;
// Add click event listener to the custom marker
markerContent.addEventListener('click', () => {
alert(`Clicked on place with ID: ${place.id}`);
});
// Use OverlayView to add the custom marker to the map
const overlay = new google.maps.OverlayView();
overlay.onAdd = function() {
const panes = this.getPanes();
panes.overlayMouseTarget.appendChild(markerContent);
};
overlay.draw = function() {
const projection = this.getProjection();
const positionPixel = projection.fromLatLngToDivPixel(position);
if (positionPixel) {
// Center the marker based on its width (95px)
markerContent.style.left = `${positionPixel.x - (95 / 2)}px`;
markerContent.style.top = `${positionPixel.y - (95 / 2)}px`;
}
};
overlay.setMap(this.map);
// Save the marker reference
this.markers.push(overlay);
},
// Fit map bounds to show all markers
fitBounds() {
const bounds = new google.maps.LatLngBounds();
this.places.forEach(place => {
bounds.extend(new google.maps.LatLng(place.coordinates.lat, place.coordinates.lng));
});
this.map.fitBounds(bounds);
},
// Clear markers from the map
clearMarkers() {
this.markers.forEach(marker => {
marker.setMap(null);
});
this.markers = []; // Clear the markers array
}
}
};
</script>
<style scoped>
.GOOGLEmap1 {
width: 100%;
height: 100%;
position: absolute;
top: 0px;
left: 0px;
z-index: 9;
}
</style>