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

Custom marker dynamically #25

Closed
thanhthaohoang opened this issue Jun 18, 2018 · 8 comments
Closed

Custom marker dynamically #25

thanhthaohoang opened this issue Jun 18, 2018 · 8 comments

Comments

@thanhthaohoang
Copy link

thanhthaohoang commented Jun 18, 2018

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>
@ulises58
Copy link

ulises58 commented Jan 4, 2019

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

@thanhthaohoang
Copy link
Author

thanhthaohoang commented Jan 4, 2019

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 optionsconstant when the map is ready.
I don't know if it answers your question 😬

@ulises58
Copy link

ulises58 commented Jan 4, 2019

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.

@thanhthaohoang
Copy link
Author

@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 ?

@ulises58
Copy link

ulises58 commented Jan 4, 2019

@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)
       },

@thanhthaohoang
Copy link
Author

thanhthaohoang commented Jan 4, 2019

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.

@ulises58
Copy link

ulises58 commented Jan 4, 2019

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

@thanhthaohoang
Copy link
Author

thanhthaohoang commented Jan 4, 2019

@ulises58 Glad that I helped and that you found the solution on your own !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants