Custom marker dynamically
thanhthaohoang opened this issue ยท 8 comments
Hi !
I would like to custom one marker on click or on hover. It could be by reducing its opacity or changing its icon.
I created my own component like this :
My component markerPlaces.vue
<template lang="html">
<div> </div>
</template>
<script>
import { MapElement } from 'vue-googlemaps'
import markerIcon from '~/assets/img/location-pointer.svg'
import { EventBus } from '~/plugins/event-bus.js'
// Those Vue props will update automatically
// (Two-way binding with .sync modifier)
const boundProps = [
'animation',
'clickable',
'cursor',
]
// Events from Google Maps emitted as Vue events
const redirectedEvents = [
'click',
'rightclick',
]
export default {
data () {
return {
// create new options object with origin property
// allows reactivity on filtering
opt: {
position : {},
icon: {}
}
}
},
mixins: [
MapElement
],
props: ['marker'],
// When Google Maps is ready
async googleMapsReady () {
const options = await Object.assign(this.opt, {
position: this.marker.position,
icon: {
url: markerIcon,
scaledSize: new window.google.maps.Size(25, 32)
}
}, this.$props)
options.map = this.$_map
// Create Google Maps objects
this.$_marker = new window.google.maps.Marker(options)
// Bind the Vue props
this.bindProps(this.$_marker, boundProps)
// Emit the events from Google Maps
this.redirectEvents(this.$_marker, redirectedEvents)
},
beforeDestroy () {
// Teardown
if (this.$_marker) {
// console.log('marker hidden', this.$_marker.marker);
this.$_marker.setMap(null)
}
}
}
</script>
My vue
<template>
<no-ssr>
<section style="width: 100%" class="map">
<googlemaps-map
ref="mapRef"
:center.sync="center"
:zoom.sync="zoom"
:options="mapOptions"
@ready="ready"
>
<googlemaps-user-position
:clickable="true"
@click="centerOnUser"
:positionStyle="positionStyle"
@update:position="setUserPosition" />
<markers-places
v-for="(marker, index) of markers"
:key="marker.id"
:marker="marker"
:class="{activeMarker: marker.id == selected}"
@click="updateStateMarker(marker, index)"
>
</markers-places>
</googlemaps-map>
<div class="map__overlay"></div>
</section>
</no-ssr>
</template>
<script>
import mapStyle from '~/assets/json/mapStyle.json'
import * as VueGoogleMaps from 'vue-googlemaps'
import { EventBus } from '~/plugins/event-bus.js'
import markersPlaces from './markersPlaces.vue'
import markerUser from './markerUser.vue'
export default {
name: 'mapComponent',
data () {
return {
center: { lat: 47.218371, lng: -1.553621 },
zoom: 14,
mapOptions: {
gestureHandling: 'greedy',
draggable: true,
zoomControl: true,
mapTypeId: 'roadmap',
styles: mapStyle
},
positionStyle: {
path: 'M2.1999999999999993,11a8.8,8.8 0 1,0 17.6,0a8.8,8.8 0 1,0 -17.6,0',
fillColor: '#2E86DE',
fillOpacity: 1,
scale: 1,
strokeColor: '#8FBBE7',
strokeWeight: 5
},
userPosition: {lat: 48.8445639, lng: 2.422224},
selected: undefined
}
},
components: {
'markers-places': markersPlaces,
'marker-user': markerUser
},
computed: {
// userCoordinates() {
// return this.$store.getters['geolocation/getUserPosition']
// },
isLocated() {
return this.$store.getters['geolocation/getIsLocated']
},
markers() {
// console.log('markers', this.$store.getters['geolocation/getLocations']);
return this.$store.getters['geolocation/getLocations']
}
},
created () {
EventBus.$on('i-got-swiped', index => {
this.panToMarker(index)
})
},
methods: {
setUserPosition(position) {
console.log('position', position);
this.userPosition = position
// push the last watch position in store
this.$store.dispatch('geolocation/setUserPosition', this.userPosition )
},
ready () {
this.$refs.mapRef.resize()
},
centerOnUser () {
if (this.userPosition) {
if (this.zoom <= 12) {
this.zoom = Math.max(15, 12)
}
this.$refs.mapRef.panTo(this.userPosition)
}
},
updateStateMarker (marker, index) {
if (this.zoom <= 12) {
this.zoom = Math.max(15, 12)
}
if(marker !== undefined) {
this.selected = marker.id
this.$refs.mapRef.panTo(marker.position)
}
// Send the event on a channel (i-got-clicked) with a payload (index of the clicked marker.)
EventBus.$emit('i-got-clicked', index)
},
panToMarker (index) {
if (this.zoom <= 12) {
this.zoom = Math.max(15, 12)
}
if(this.markers[index] !== undefined) {
this.center = this.markers[index].position
}
}
}
}
</script>
hello how I'm starting to work with the modified markers, I have a question how do you actuate the position of the marker? @thanhthaohoang
Hi @ulises58 !
In my parent component, I send a prop called marker
to my child component marker-places
. That prop contains an object with a key position
with coordinates values.
In the child component, I'm just attributing the sent position in the options
constant when the map is ready.
I don't know if it answers your question ๐ฌ
Hello @thanhthaohoang , I think I did my question wrong, how to update the position of the marker after it was created for the first time?
<custom-marker
v-for="(marker, index) of markers"
:key="marker.id"
:marker="marker"
:position = "marker.position"
>
Is this the correct way in which I must send to update the position?
I am using the same component markerPlaces code.
I am very new to this, thank you very much for your help. I know my question is very silly but I see that you have done it in a very good way.
@ulises58 To update the marker position, you can change the value of marker.position
that you send as a value prop in your child component custom-marker
. Did you try this before ?
@thanhthaohoang 0.0 Don't you mean something like this?
props: ['marker','position'],
// When Google Maps is ready
async googleMapsReady () {
//https://pastebin.com/VYMCvS9m
console.log(this.marker.position)
const options = await Object.assign(this.opt, {
position: this.marker.position,
icon: {
url: 'https://maps.google.com/mapfiles/kml/shapes/parking_lot_maps.png',
scaledSize: new window.google.maps.Size(25, 32)
}
}, this.$props)
options.map = this.$_map
// Create Google Maps objects
this.$_marker = new window.google.maps.Marker(options)
// Bind the Vue props
this.bindProps(this.$_marker, boundProps)
// Emit the events from Google Maps
this.redirectEvents(this.$_marker, redirectedEvents)
},
const options = await Object.assign(this.opt, {
position: this.marker.position,
icon: {
url: 'https://maps.google.com/mapfiles/kml/shapes/parking_lot_maps.png',
scaledSize: new window.google.maps.Size(25, 32)
}
}, this.$props)
In your code, position
can take the value of the position
prop that you stated earlier. Indeed, when you'll change the value of the position
prop from your parent component, the position of your marker will be updated too I think.
Hi, thank you very much, I realized what my mistake was. Which is here
const boundProps = [
'animation',
'clickable',
'cursor',
'position'
]
the position property was missing
thanks for your time @thanhthaohoang
@ulises58 Glad that I helped and that you found the solution on your own !