How delete vertex (node) on Polygon with Hole (Google Maps V3)

前端 未结 1 1273
佛祖请我去吃肉
佛祖请我去吃肉 2021-01-24 09:00

I have taken this example (solution) from Ian Grainger, but I added a Polygon with inner hole.

This example work fine for outer vertex path, but not for inner vertex pa

1条回答
  •  悲&欢浪女
    2021-01-24 09:38

    One of your issues is polygon with a hole in it has multiple (in this case two) paths, and you aren't adding listeners for changes on both paths. Below is a proof of concept, it isn't perfect, sometimes markers are orphaned, but should be a starting point. Double click on the blue markers underneath the vertices to delete them (I couldn't get your "X" to reliably work).

    proof of concept fiddle

    updated proof of concept with white markers

    code snippet:

    var G = google.maps;
    var zoom = 8;
    var centerPoint = new G.LatLng(37.286172, -121.80929);
    var map;
    
    
    $(function() {
      // create options object
      var myOptions = {
        center: centerPoint,
        zoom: zoom,
        mapTypeId: G.MapTypeId.ROADMAP
      };
    
      // create map with options
      map = new G.Map($("#map_canvas")[0], myOptions);
    
      addPolygon(map);
    });
    
    
    function addPolygon(map) {
      var paths = [
        [new G.LatLng(37.686172, -122.20929),
          new G.LatLng(37.696172, -121.40929),
          new G.LatLng(36.706172, -121.40929),
          new G.LatLng(36.716172, -122.20929),
          new G.LatLng(37.686172, -122.20929)
        ],
    
        [new G.LatLng(37.486172, -122.00929),
          new G.LatLng(37.086172, -122.00929),
          new G.LatLng(37.086172, -121.60929),
          new G.LatLng(37.486172, -121.60929),
          new G.LatLng(37.486172, -122.00929)
        ]
      ];
    
      poly = new G.Polygon({
        clickable: false,
        paths: paths,
        map: map
      });
      polygonBinder(poly);
      poly.setEditable(true);
      G.event.addListener(poly.getPaths().getAt(0), 'insert_at', addClickMarker0);
      G.event.addListener(poly.getPaths().getAt(1), 'insert_at', addClickMarker1);
    }
    
    function polygonBinder(poly) {
      poly.binder0 = new MVCArrayBinder(poly.getPaths().getAt(0));
      poly.binder1 = new MVCArrayBinder(poly.getPaths().getAt(1));
      poly.markers = [];
      for (var i = 0; i < poly.getPaths().getLength(); i++) {
        poly.markers[i] = [];
        for (var j = 0; j < poly.getPaths().getAt(i).getLength(); j++) {
          var mark = new G.Marker({
            map: map,
            icon: {
              path: G.SymbolPath.CIRCLE,
              scale: 8,
              strokeWeight: 2,
              strokeColor: 'blue',
              fillColor: 'blue',
              fillOpacity: 1
            },
            draggable: true,
            title: "double click to delete [" + i + "," + j + "]",
            position: poly.getPaths().getAt(i).getAt(j)
          });
          poly.markers[i][j] = mark;
          mark.bindTo('position', poly["binder" + i], (j).toString());
          G.event.addListener(mark, "dblclick", deleteMark);
        }
      }
    
    }
    
    function addClickMarker0(index) {
      addClickMarker(index, 0);
    }
    
    function addClickMarker1(index) {
      addClickMarker(index, 1);
    }
    
    function deleteMark(evt) {
      var minDist = Number.MAX_VALUE;
      var minPathIdx = -1;
      var minIdx = -1;
      var i, j;
      for (i = 0; i < poly.getPaths().getLength(); i++) {
        for (j = 0; j < poly.getPaths().getAt(i).getLength(); j++) {
          var distance = G.geometry.spherical.computeDistanceBetween(evt.latLng, poly.getPaths().getAt(i).getAt(j));
          if (distance < minDist) {
            minDist = distance;
            minPathIdx = i;
            minIdx = j;
          }
          if (distance < 10) {
            document.getElementById('info').innerHTML = "deleted path=" + i + " idx=" + j + " dist<10 minDist=" + minDist + " meters";
            poly.getPaths().getAt(i).removeAt(j);
            break;
          }
        }
      }
      if ((i == poly.getPaths().getLength()) && (j == poly.getPaths(i - 1).getLength())) {
        poly.getPaths().getAt(minPathIdx).removeAt(minIdx);
        document.getElementById('info').innerHTML = "deleted path=" + minPathIdx + " idx=" + minIdx + " dist=" + minDist + " meters";
      }
      this.setMap(null);
    }
    
    function addClickMarker(index, pathIdx) {
      var path = this;
      // rebind binder
      for (var i = 0; i < poly.markers[pathIdx].length; i++) {
        poly.markers[pathIdx][i].setMap(null);
      }
      poly.markers[pathIdx] = [];
      for (var i = 0; i < poly.getPaths().getAt(pathIdx).getLength(); i++) {
        var mark = new G.Marker({
          map: map,
          icon: {
            path: G.SymbolPath.CIRCLE,
            scale: 8,
            strokeWeight: 2,
            strokeColor: 'blue',
            fillColor: 'blue',
            fillOpacity: 1
          },
          draggable: true,
          title: "double click to delete [" + pathIdx + "," + i + "]",
          position: poly.getPaths().getAt(pathIdx).getAt(i)
        });
        poly.markers[pathIdx][i] = mark;
        mark.bindTo('position', poly["binder" + pathIdx], (i).toString());
        G.event.addListener(mark, "dblclick", deleteMark);
      }
    }
    
    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);
      }
    }
    html,
    body,
    #map_canvas {
      height: 100%;
      width: 100%;
      margin: 0;
      padding: 0
    }
    
    
    

    0 讨论(0)
提交回复
热议问题