Search code examples
javascriptgoogle-maps-api-3draggable

Google Maps Geometry Library: how do I create a marker that is in a state of being dragged


My intention is to split a polyline (with two coordinates) in two on dragstart event.

What is happening in code below:

  1. Polyline is waiting for dragstart
  2. When user starts dragging Polyline, two new Polylines and a Marker in between them replace the old Polyline
  3. Dragging stops at current mouse location without releasing mouse

Actual intention:

In step 3, dragging continues, but dragged element is the new Marker and not the removed Polyline.

How do I transfer "dragging" from Polyline to a Marker?

const path = new google.maps.MVCArray([
  new google.maps.LatLng(0, 0),
  new google.maps.LatLng(10, 10),
])

const polyline = new google.maps.Polyline({
  map,
  path,
  draggable: true
})

let marker, newPolylineA, newPolylineB

const dragstartListener = polyline.addListener('dragstart', ({ latLng }) => {
  google.maps.event.removeListener(dragstartListener)
  polyline.setMap(null)

  marker = new google.maps.Marker({
    map,
    position: latLng,
    draggable: true,
  })

  newPolylineA = new google.maps.Polyline({
    map,
    path: [ path.getAt(0), latLng ],
  })

  newPolylineB = new google.maps.Polyline({
    map,
    path: [ latLng, path.getAt(1) ],
  })
})


Solution

  • I solved it by hiding original Polyline with strokeOpacity and using drag and dragend events.

    It's not actual swap of drag targets, but it at least imitates the result.

    const coordinateA = new google.maps.LatLng(0, 0)
    const coordinateB = new google.maps.LatLng(10, 10)
    const path = new google.maps.MVCArray([
      coordinateA,
      coordinateB,
    ])
    
    const polyline = new google.maps.Polyline({
      map,
      path,
      draggable: true
    })
    
    let marker, newPolylineA, newPolylineB
    
    const dragstartListener = polyline.addListener('dragstart', ({ latLng }) => {
      polyline.setOptions({
        strokeOpacity: 0
      })
    
      marker = new google.maps.Marker({
        map,
        position: latLng,
        draggable: true,
      })
    
      newPolylineA = new google.maps.Polyline({
        map,
        path: [ path.getAt(0), latLng ],
      })
    
      newPolylineB = new google.maps.Polyline({
        map,
        path: [ latLng, path.getAt(1) ],
      })
    
      google.maps.event.removeListener(dragstartListener)
    })
    
    const dragListener = polyline.addListener('drag', ({ latLng }) => {
      marker.setPosition(latLng)  
      newPolylineA.setPath([ coordinateA, latLng ])
      newPolylineB.setPath([ latLng, coordinateB ])
    })
    
    const dragendListener = polyline.addListener('dragend', ({ latLng }) => {
      google.maps.event.removeListener(dragendListener)
      google.maps.event.removeListener(dragListener)
    
      marker.setPosition(latLng)  
      newPolylineA.setPath([ coordinateA, latLng ])
      newPolylineB.setPath([ latLng, coordinateB ])
    
      polyline.setMap(null)
    })