Avoiding vertex drag maps api v3

2020-07-30 02:35发布

问题:

Very simple. I want to avoid the dragging of the first and last vertices. I've tried using dragstart event, but apparently polyline doesn't listen to that one.

I've managed to do something with set_at. I have the last position stored, when set_at is called, I check the index of that vertex, and then set the latLng for that vertex to the old one. This was only possible using setAt function which fires the event again.

So a created a ignoreNextEvent flag, so It won't go for an infinite loop.

problem is, setAt function os used plenty of times by the maps api, and the solution, although works, is not perfect and I need to worry about ignoreNextEvent everytime I'm interacting with the polyline.

I'm trying to find a way to accomplish that, can anyone help?

The working code:

google.maps.event.addListener(cable.getPath(), 'set_at', function(e){
    if(!ignoreNextEvent){
        if(e == 0 || e == cable.getPath().length-1){
            var point = new google.maps.LatLng(cable.Cable.vertex[e].latitude, cable.Cable.vertex[e].longitude);
            ignoreNextEvent = true;
            cable.getPath().setAt(e,point);
        }else{
            if(cable.Cable.idx != 0){ saveCable(index, cable.Cable.destination_idx); }  
        }
    }else{
        ignoreNextEvent = false;
    }
});

回答1:

Create a polyline, bind draggable markers to the vertices that you want to be able to drag, bind markers that aren't draggable to the vertices that you don't want to be able to drag.

example

var gmarkers = [];
var map;

  function addLatLng(event) {
    var path = poly.getPath();
    path.push(event.latLng);
    var len = path.getLength();
    var marker = new google.maps.Marker({
      position: event.latLng,
      title: '#' + len,
      map: map,
      icon: {
        url: "https://maps.gstatic.com/intl/en_us/mapfiles/markers2/measle.png",
        size: new google.maps.Size(7,7),
        anchor: new google.maps.Point(4,4)
      },
      draggable : true
    });
    gmarkers.push(marker);
    marker.bindTo('position', poly.binder, (len-1).toString());
  }

function initialize() {
  var polyOptions = {
      strokeColor: '#000000',
      strokeOpacity: 1.0,
      strokeWeight: 3, map: map
    };
  poly = new google.maps.Polyline(polyOptions);
  var bounds = new google.maps.LatLngBounds();
  map = new google.maps.Map(document.getElementById('map_canvas'), {
    center: new google.maps.LatLng(10.9386, -84.888),
    zoom: 10,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  });

  poly.binder = new MVCArrayBinder(poly.getPath());
  for(var i = 0; i < locations.length; i++) {
    var evt = {};
    evt.latLng = new google.maps.LatLng(locations[i][0], locations[i][1]);
    bounds.extend(evt.latLng);
    addLatLng(evt);
  }
  gmarkers[0].setDraggable(false);
  gmarkers[gmarkers.length-1].setDraggable(false);


  poly.setMap(map);
  map.fitBounds(bounds);
} 
google.maps.event.addDomListener(window, "load", initialize);

  /*
   * Use bindTo to allow dynamic drag of markers to refresh poly.
   */

  function MVCArrayBinder(mvcArray){
    this.array_ = mvcArray;
  }
  MVCArrayBinder.prototype = new google.maps.MVCObject();
  MVCArrayBinder.prototype.get = function(key) {
    if (!isNaN(parseInt(key))){
      return this.array_.getAt(parseInt(key));
    } else {
      this.array_.get(key);
    }
  }
  MVCArrayBinder.prototype.set = function(key, val) {
    if (!isNaN(parseInt(key))){
      this.array_.setAt(parseInt(key), val);
    } else {
      this.array_.set(key, val);
    }
  }

code snippet:

/*
 * Use bindTo to allow dynamic drag of markers to refresh poly.
 */

function MVCArrayBinder(mvcArray) {
  this.array_ = mvcArray;
}
MVCArrayBinder.prototype = new google.maps.MVCObject();
MVCArrayBinder.prototype.get = function(key) {
  if (!isNaN(parseInt(key))) {
    return this.array_.getAt(parseInt(key));
  } else {
    this.array_.get(key);
  }
}
MVCArrayBinder.prototype.set = function(key, val) {
  if (!isNaN(parseInt(key))) {
    this.array_.setAt(parseInt(key), val);
  } else {
    this.array_.set(key, val);
  }
}

/**
 * Handles click events on a map, and adds a new point to the Polyline.
 * @param {MouseEvent} mouseEvent
 */
function addLatLng(event) {
  var path = poly.getPath();
  path.push(event.latLng);
  var len = path.getLength();
  var marker = new google.maps.Marker({
    position: event.latLng,
    title: '#' + len,
    map: map,
    icon: {
      url: "https://maps.gstatic.com/intl/en_us/mapfiles/markers2/measle.png",
      size: new google.maps.Size(7, 7),
      anchor: new google.maps.Point(4, 4)
    },
    draggable: true
  });
  gmarkers.push(marker);
  marker.bindTo('position', poly.binder, (len - 1).toString());
}
var locations = [
  [-33.890542, 151.274856, 4, 'Bondi Beach'],
  [-33.923036, 151.259052, 5, 'Coogee Beach'],
  [-34.028249, 151.157507, 3, 'Cronulla Beach'],
  [-33.80010128657071, 151.28747820854187, 2, 'Manly Beach'],
  [-33.950198, 151.259302, 1, 'Maroubra Beach']
];

var poly;
var map;
var gmarkers = [];

function initialize() {
  var polyOptions = {
    strokeColor: '#000000',
    strokeOpacity: 1.0,
    strokeWeight: 3,
    map: map
  };
  poly = new google.maps.Polyline(polyOptions);
  var bounds = new google.maps.LatLngBounds();
  map = new google.maps.Map(document.getElementById('map_canvas'), {
    center: new google.maps.LatLng(10.9386, -84.888),
    zoom: 10,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  });

  poly.binder = new MVCArrayBinder(poly.getPath());
  for (var i = 0; i < locations.length; i++) {
    var evt = {};
    evt.latLng = new google.maps.LatLng(locations[i][0], locations[i][1]);
    bounds.extend(evt.latLng);
    addLatLng(evt);
  }
  gmarkers[0].setDraggable(false);
  gmarkers[0].setIcon({
    url: "https://maps.gstatic.com/intl/en_us/mapfiles/markers2/measle_blue.png",
    size: new google.maps.Size(7, 7),
    anchor: new google.maps.Point(4, 4)
  });
  gmarkers[gmarkers.length - 1].setDraggable(false);
  gmarkers[gmarkers.length - 1].setIcon({
    url: "https://maps.gstatic.com/intl/en_us/mapfiles/markers2/measle_blue.png",
    size: new google.maps.Size(7, 7),
    anchor: new google.maps.Point(4, 4)
  });


  poly.setMap(map);
  map.fitBounds(bounds);
}

google.maps.event.addDomListener(window, "load", initialize);
html,
body,
#map_canvas {
  width: 100%;
  height: 100%;
  margin: 0px;
  padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<div id="map_canvas"></div>