inocan-group / vue3-google-map

A set of composable components for easy use of Google Maps in your Vue 3 projects.
https://vue3-google-map.com
MIT License
264 stars 51 forks source link

InfoWindow doesn't work with CustomMarker #124

Closed ffninja closed 11 months ago

ffninja commented 1 year ago

Issue still happen which was described in https://github.com/inocan-group/vue3-google-map/issues/94, when put InfoWindow in CustomMarker, it doesn't work...

HusamElbashir commented 1 year ago

This feature isn't supported unfortunately.

Usman-Ejaz commented 1 year ago

Any update on this issue? I'm still facing this issue.

Usman-Ejaz commented 1 year ago

@ffninja did you manage to solve this issue? Any custom stuff you did for your scenario?

HoekWax commented 1 year ago

@ffninja did you manage to solve this issue? Any custom stuff you did for your scenario?

Hey, I have the same issue, what I'm trying to do now is to have a CustomMarker and a Marker ate the same spot

<GoogleMap
        :id="mapId"
        ref="mapRef"
        :fullscreen-control="false"
        :map-type-control="false"
        :street-view-control="false"
        :api-key="useRuntimeConfig().public.googleMapApiKey"
        style="width: 100%"
        :center="center"
        :zoom="10"
    >
        <template v-for="marker in markers" :key="marker.id">
            <Marker
                :options="{
                    position: marker.position,
                    options: {
                        // En mettant une shape, je peux récupérer les markers avec la classe 'gmimap${ID_DU_MARKER - 1}'
                        shape: {
                            type: 'circle',
                            coords: [
                                marker.position.lat,
                                marker.position.lng,
                                100,
                            ],
                        },
                        icon: 'fail.png',
                    },
                }"
            >
                <UiAtomMapEventInfoWindow
                    v-if="marker.event"
                    :event="marker.event"
                ></UiAtomMapEventInfoWindow>
            </Marker>
            <CustomMarker
                :options="{ position: marker.position }"
                @click="customMarkerClicked(marker)"
            >
                <div
                    class="overflow-hidden rounded-full border-4 border-primary bg-white"
                >
                    <img
                        :src="
                            marker.event?.organization?.logo ||
                            marker.event?.cover
                        "
                        class="h-[60px] w-[60px] object-cover"
                    />
                </div>
            </CustomMarker>
        </template>
    </GoogleMap>

I hide the Marker icon with logo:'fail.png', I add the "shape" in "options" in order for an element to have a class with an Id that I can catch to trigger a click on the Marker when the user clicks on the CustomMarker

It's ugly, It's not working too well because I didn't manage to add the id that I want on a Marker, so I don't know how to get the marker and then click on it programatically.

I use the class gmimap[MARKER_ID] but the id changed when there is a refresh or if you change the number of markers on your map

Here is what I do when the customMarker is clicked, I try to get the element using the gmimap class and the ID. But each time there is a hot reload the id changed


function getClickableMarkerElement(markerId: number): Element | undefined {
    for (let i = 0; i < 100; i++) {
        const element = document.getElementById(
            `gmimap${markerId - 1 + i * props.markers.length}`
        );
        if (element) {
            return element;
        }
    }
}

function customMarkerClicked(marker: MarkerType) {
    const element = getClickableMarkerElement(marker.id)
        ?.parentNode as HTMLDivElement;

    element?.click();
}
ffninja commented 1 year ago

@ffninja did you manage to solve this issue? Any custom stuff you did for your scenario?

Hey, I have the same issue, what I'm trying to do now is to have a CustomMarker and a Marker ate the same spot

<GoogleMap
        :id="mapId"
        ref="mapRef"
        :fullscreen-control="false"
        :map-type-control="false"
        :street-view-control="false"
        :api-key="useRuntimeConfig().public.googleMapApiKey"
        style="width: 100%"
        :center="center"
        :zoom="10"
    >
        <template v-for="marker in markers" :key="marker.id">
            <Marker
                :options="{
                    position: marker.position,
                    options: {
                        // En mettant une shape, je peux récupérer les markers avec la classe 'gmimap${ID_DU_MARKER - 1}'
                        shape: {
                            type: 'circle',
                            coords: [
                                marker.position.lat,
                                marker.position.lng,
                                100,
                            ],
                        },
                        icon: 'fail.png',
                    },
                }"
            >
                <UiAtomMapEventInfoWindow
                    v-if="marker.event"
                    :event="marker.event"
                ></UiAtomMapEventInfoWindow>
            </Marker>
            <CustomMarker
                :options="{ position: marker.position }"
                @click="customMarkerClicked(marker)"
            >
                <div
                    class="overflow-hidden rounded-full border-4 border-primary bg-white"
                >
                    <img
                        :src="
                            marker.event?.organization?.logo ||
                            marker.event?.cover
                        "
                        class="h-[60px] w-[60px] object-cover"
                    />
                </div>
            </CustomMarker>
        </template>
    </GoogleMap>

I hide the Marker icon with logo:'fail.png', I add the "shape" in "options" in order for an element to have a class with an Id that I can catch to trigger a click on the Marker when the user clicks on the CustomMarker

It's ugly, It's not working too well because I didn't manage to add the id that I want on a Marker, so I don't know how to get the marker and then click on it programatically.

I use the class gmimap[MARKER_ID] but the id changed when there is a refresh or if you change the number of markers on your map

Here is what I do when the customMarker is clicked, I try to get the element using the gmimap class and the ID. But each time there is a hot reload the id changed


function getClickableMarkerElement(markerId: number): Element | undefined {
    for (let i = 0; i < 100; i++) {
        const element = document.getElementById(
            `gmimap${markerId - 1 + i * props.markers.length}`
        );
        if (element) {
            return element;
        }
    }
}

function customMarkerClicked(marker: MarkerType) {
    const element = getClickableMarkerElement(marker.id)
        ?.parentNode as HTMLDivElement;

    element?.click();
}

yeah, I came up with same solution. And Thank you for your sharing, I hope it will help others

HoekWax commented 1 year ago

@ffninja Did you manage to find something more stable than the class "gmimap" ? Because when I add new markers the id at the end of the class keeps going up.

HoekWax commented 1 year ago

I find a better way to do it, I changed the options of the marker to :

                :options="{
                    position: marker.position,
                    options: {
                        // Title here is VERY important for the infoWindow to work
                        title: getMarkerTitle(marker.id),
                        icon: 'fail.png',
                    },
                }"

Then for the click event I have this

function getMarkerTitle(markerId: number) {
    return `marker_title_${markerId}`;
}

function customMarkerClicked(marker: MarkerType) {
    const element = document.querySelector(
        `[aria-label="${getMarkerTitle(marker.id)}"]`
    ) as HTMLDivElement;

    element?.click();
}
MarcyLina commented 1 year ago

My colleague and I found a pretty straightforward way that worked for us. Instead of using the CustomMarker with the info window, we were able to use the regular Marker. We tapped directly into Google API's :icon attribute within the :options object. Here is what the template looks like:

<template>
    <Marker
        :options="{position: position, icon: icon}"
    >
        <InfoWindow
                     // your code
        </InfoWindow>
    </Marker>
</template>

And then we created a computed property with our custom marker path:

computed: {
    icon() {
        return {
            url: '/images/custom-icon.png',
            scaledSize: { width: 27, height: 39 }  
        };
    },
},

I'd also like to note, several different markers are in use on the project I am working on so I was able to conditionally render different markers with no issues using an if/else:

computed: {
    icon() {
        if(condition) {
             return {
                 url: '/images/icon-1.png',
                 scaledSize: { width: 30, height: 40 }  
            };
        } else {
             return {
                 url: '/images/icon-2.png',
                 scaledSize: { width: 20, height: 30 }  
            };
        }        
    },
},

I hope this can help someone!