【问题标题】:Fire event after polygon is loaded加载多边形后触发事件
【发布时间】:2016-04-22 03:25:26
【问题描述】:

找了一整天也没找到答案。

所以问题是:
我有一个用户可以在上面绘制的谷歌地图。之后,用户可以将其保存在服务器上。它工作正常。下面是绘制代码:

var drawingManager;
var selectedShape;
var colors = ['#1E90FF', '#FF1493', '#32CD32', '#FF8C00', '#4B0082'];
var selectedColor;
var colorButtons = {};
var all_overlays = [];
var coordinates;
var polygon;
var globalGoogleSelectedColor;
var globalGooglePinWidth;
var map;
coordObj = new Object();

function clearSelection() 
{
  if (selectedShape) 
  {
    deleteAllLastShape(); 
    selectedShape.setEditable(false);
    selectedShape = null;
    deleteObjectContent(coordObj);
  }
}

function setSelection(shape) 
{
  clearSelection();
  selectedShape = shape;
  shape.setEditable(true);
  selectColor(shape.get('fillColor') || shape.get('strokeColor'));
}

function deleteAllShape() 
{
  console.log("deleteAllShape");
  deleteObjectContent(coordObj);

  for (var i=0; i < all_overlays.length; i++)
  {
    all_overlays[i].overlay.setMap(null);
  }

  all_overlays = [];
}

function deleteAllLastShape() 
{
  var myLenth = all_overlays.length;

  if(myLenth > 1)
  {
    all_overlays[0].overlay.setMap(null);
    all_overlays = _.rest(all_overlays);
  }
}

function deleteSelectedShape() 
{
  if (selectedShape) 
  {
    selectedShape.setMap(null);
    deleteObjectContent(coordObj);
  }
}

function selectColor(color)
{
  selectedColor = color;
  globalGoogleSelectedColor = selectedColor;
  globalGooglePinWidth = 2; //only for Database

  for (var i = 0; i < colors.length; ++i) 
  {
    var currColor = colors[i];
    colorButtons[currColor].style.border = currColor == color ? '2px solid #789' : '2px solid #fff';
  }

  // Retrieves the current options from the drawing manager and replaces the
  // stroke or fill color as appropriate.
  var polylineOptions = drawingManager.get('polylineOptions');
  polylineOptions.strokeColor = color;
  drawingManager.set('polylineOptions', polylineOptions);

  var rectangleOptions = drawingManager.get('rectangleOptions');
  rectangleOptions.fillColor = color;
  drawingManager.set('rectangleOptions', rectangleOptions);

  var circleOptions = drawingManager.get('circleOptions');
  circleOptions.fillColor = color;
  drawingManager.set('circleOptions', circleOptions);

  var polygonOptions = drawingManager.get('polygonOptions');
  polygonOptions.fillColor = color;
  drawingManager.set('polygonOptions', polygonOptions);
}

function setSelectedShapeColor(color)
{
  if (selectedShape)
  {
    if (selectedShape.type == google.maps.drawing.OverlayType.POLYLINE)
    {
      selectedShape.set('strokeColor', color);
    }
    else
    {
      selectedShape.set('fillColor', color);
    }
  }
}

function makeColorButton(color)
{
  var button = document.createElement('span');
  button.className = 'color-button';
  button.style.backgroundColor = color;
  google.maps.event.addDomListener(button, 'click', function() {
    selectColor(color);
    setSelectedShapeColor(color);
  });

  return button;
}

function buildColorPalette()
{
  var colorPalette = document.getElementById('color-palette');

  for (var i = 0; i < colors.length; ++i)
  {
    var currColor = colors[i];
    var colorButton = makeColorButton(currColor);
    colorPalette.appendChild(colorButton);
    colorButtons[currColor] = colorButton;
  }

  selectColor(colors[0]);
}

function initializeAreas() 
{
    map = new google.maps.Map(document.getElementById('mapBaugebieteDiv'), 
    {
      zoom: 15,
      center: new google.maps.LatLng(48.758961357888516,8.240861892700195),
      mapTypeControlOptions: {
      style: google.maps.MapTypeControlStyle.DEFAULT,
      mapTypeIds: [
        google.maps.MapTypeId.ROADMAP,
        google.maps.MapTypeId.TERRAIN,
        google.maps.MapTypeId.SATELLITE,
        google.maps.MapTypeId.HYBRID
      ]},
      disableDefaultUI: false,
      zoomControl: true,
      scaleControl: true,
      mapTypeControl: true,
      streetViewControl: true,
      rotateControl: true
    });

    var polyOptions = 
    {
      strokeWeight: 0,
      fillOpacity: 0.45,
      editable: true
    };

    // Creates a drawing manager attached to the map that allows the user to draw
    // markers, lines, and shapes.
    drawingManager = new google.maps.drawing.DrawingManager(
    {
      drawingMode: google.maps.drawing.OverlayType.POLYGON,
      drawingControl: true,
      drawingControlOptions: {
        position: google.maps.ControlPosition.TOP_CENTER,
        drawingModes: [
            // google.maps.drawing.OverlayType.MARKER,
            // google.maps.drawing.OverlayType.CIRCLE,
            google.maps.drawing.OverlayType.POLYLINE,
            // google.maps.drawing.OverlayType.RECTANGLE,
            google.maps.drawing.OverlayType.POLYGON
          ]
      },
      markerOptions: 
      {
        draggable: true
      },
      polylineOptions: 
      {
        editable: true
      },
      rectangleOptions: polyOptions,
      circleOptions: polyOptions,
      polygonOptions: polyOptions,
      map: map
    });

    google.maps.event.addListener(drawingManager, 'overlaycomplete', function(e) 
    {
      // Push the overlay onto an array (all_overlays):
      all_overlays.push(e);
      deleteAllLastShape();

      if (e.type != google.maps.drawing.OverlayType.MARKER) 
      {
        // Switch back to non-drawing mode after drawing a shape.
        drawingManager.setDrawingMode(null);

        // Add an event listener that selects the newly-drawn shape when the user
        // mouses down on it.
        var newShape = e.overlay;
        newShape.type = e.type;

        google.maps.event.addListener(newShape, 'click', function() 
        {
          setSelection(newShape);
        });
        setSelection(newShape);
      }
    });

    // Clear the current selection when the drawing mode is changed, or when the
    // map is clicked.
    google.maps.event.addListener(drawingManager, 'drawingmode_changed', clearSelection);
    google.maps.event.addListener(map, 'click', clearSelection);
    google.maps.event.addDomListener(document.getElementById('delete-button'), 'click', deleteSelectedShape);
    google.maps.event.addDomListener(document.getElementById('delete-all-button'), 'click', deleteAllShape);

    ///////////////////////////////////////
    // Polylgon
    ///////////////////////////////////////
    google.maps.event.addListener(drawingManager, 'polygoncomplete', function (polygon) 
    {
      var shapeType = 'polygon';
      google.maps.event.addListener(polygon.getPath(), 'insert_at', function()
      {
        // New point
        coordinates = (polygon.getPath().getArray());
        showObjectContent(coordinates);
        coordObj = getCoordinatesOfPolygon(polygon,shapeType);
      });

      google.maps.event.addListener(polygon.getPath(), 'remove_at', function()
      {
        // Point was removed
        coordinates = (polygon.getPath().getArray());
        coordObj = getCoordinatesOfPolygon(polygon,shapeType);
      });

      google.maps.event.addListener(polygon.getPath(), 'set_at', function()
      {
          // Point was moved
          coordinates = (polygon.getPath().getArray());
          coordObj = getCoordinatesOfPolygon(polygon,shapeType);
      });

      google.maps.event.addListener(polygon, 'dragend', function()
      {
        // Polygon was dragged
        coordinates = (polygon.getPath().getArray());
        coordObj = getCoordinatesOfPolygon(polygon,shapeType);
      });

      coordinates = (polygon.getPath().getArray());
      coordObj = getCoordinatesOfPolygon(polygon,shapeType);
    });

    ///////////////////////////////////////
    // Polyline
    ///////////////////////////////////////
    google.maps.event.addListener(drawingManager, 'polylinecomplete', function (polygon) 
    {
      var shapeType = 'polyline';
      google.maps.event.addListener(polygon.getPath(), 'insert_at', function()
      {
        // New point
        coordinates = (polygon.getPath().getArray());
        coordObj = getCoordinatesOfPolygon(polygon,shapeType);
      });

      google.maps.event.addListener(polygon.getPath(), 'remove_at', function()
      {
        // Point was removed
        coordinates = (polygon.getPath().getArray());
        coordObj = getCoordinatesOfPolygon(polygon,shapeType);
      });

      google.maps.event.addListener(polygon.getPath(), 'set_at', function()
      {
        // Point was moved
        coordinates = (polygon.getPath().getArray());
        coordObj = getCoordinatesOfPolygon(polygon,shapeType);
      });

      google.maps.event.addListener(polygon, 'dragend', function()
      {
        // Polygon was dragged
        coordinates = (polygon.getPath().getArray());
        coordObj = getCoordinatesOfPolygon(polygon,shapeType);
      });
      coordinates = (polygon.getPath().getArray());
      coordObj = getCoordinatesOfPolygon(polygon,shapeType);
    });

    buildColorPalette();
} 

google.maps.event.addDomListener(window, 'load', initializeAreas);

但最大的问题是,在从服务器重新加载 lat/lng 并在地图上绘制之后,事件监听器不知道新的多边形:

function fillBuildingForm(getData)
{
  var coord = getData['buildings']; // coordinates from the server

  if(typeof coord[0] !== 'undefined')
  {
    var shapeType = coord[0]['shapeType'];
    var color = coord[0]['color'];
    var strokeOpacity = coord[0]['opacity'];
    var strokeWeight = coord[0]['linewidth'];
    var numberOfCoord = getObjectSize(coord);
    var flightPlanCoordinates = new Array();

    for (var i = 0; i < numberOfCoord; i++) 
    {
      thisCoord = new Object();
      thisCoord['lat']=parseFloat(coord[i]['lat']);
      thisCoord['lng']=parseFloat(coord[i]['lng']);
      flightPlanCoordinates.push(thisCoord);
    };

    var bermudaTriangle = new google.maps.Polygon(
    {
      paths: flightPlanCoordinates,
      strokeColor: color,
      strokeOpacity: strokeOpacity,
      strokeWeight: strokeWeight,
      fillColor: color,
      fillOpacity: 0.35,
      // bounds: flightPlanCoordinates,
      editable: true,
      draggable: true
    });

    bermudaTriangle.setMap(map); //now its drawing at the map
  }
}

您可以看到,到目前为止,它运行良好:

但用户可以更改多边形并希望将新更改的多边形保存在服务器上。听众:

google.maps.event.addListener(drawingManager, 'polygoncomplete', function (polygon) 

不识别多边形已被绘制。因此侦听器无法识别用户何时更改多边形。 所以坐标不在 all_overlays[i] 中。 监听器只识别多边形是手动绘制的,而不是像上面那样自动绘制的。

问题:如何将自动绘制的多边形坐标发送到“地图”对象?或者,如何触发“多边形完成”事件,以便它识别新多边形?

我的另一个想法是:在带有坐标的地图上触发鼠标单击事件,因此侦听器必须认识到地图已更改。但不幸的是,这不起作用。

有人知道如何解决这个问题吗?

【问题讨论】:

  • 如何确认一个多边形是完整的? .. 哪些条件定义了这种情况..?
  • 在上面的第一个代码中你会看到:drawingModes: [ // google.maps.drawing.OverlayType.MARKER, // google.maps.drawing.OverlayType.CIRCLE, google.maps.drawing.OverlayType .POLYLINE, // google.maps.drawing.OverlayType.RECTANGLE, google.maps.drawing.OverlayType.POLYGON ] ----> 所以这里给了用户 2 种可能性:绘制折线或多边形,当他第一次时间来到了空地图。问题是从服务器加载并再次绘制后,听众不知道新的多边形。
  • 请提供一个Minimal, Complete, Tested and Readable example 来证明该问题。您应该能够将侦听器添加到从服务器添加到地图的多边形。
  • 拒绝投票是不公平的。我无法显示完整的问题或应用程序,因为它嵌入在客户的后端系统中,您需要登录。编写这个新的应用程序来向您展示其功能将是一项巨大的努力。

标签: google-maps events polygon send


【解决方案1】:

由于事件“polygon_load _complete”不可用,可能性不大。一个建议是利用这样一个事实:要对多边形进行操作,您必须单击它。 如果您需要管理从服务器加载多边形并且用户更改形状/坐标的情况。您可以在加载阶段为每个多边形添加点击监听器..

对于每个处于加载阶段的多边形..

var aPoly  = new google.maps.Polygon({
    paths:myPaths,
    .......
});


google.maps.event.addListener(aPoly, 'click', function (event) {
     console.log('This polygon contain : ' + this.paths + ' coords point ');
  });  

通过这种方式,您可以拦截单击多边形以管理您的需求

【讨论】:

    【解决方案2】:

    您的想法是好的意图,但不是解决方案的结束。不过谢谢你的提示。由于您的回答,我能够找到方法。

    通常我们应该认为,对象 bermudaTriangle 应该具有“路径”属性。但它不是这样工作的。

    为了获取加载的 Poly(从服务器加载)的坐标,有一个 google-map 函数,如“getPath()”或“getPaths()”。看来,这两种方法都有效。

    请注意,我已将名称从“bermudaTriangle”更改为“globalLoadedPoly”。

    所以解决方案是结合上面的代码现在附加:

    1. 创建一个全局变量:

      var globalLoadedPoly;
      

      (全局不是必需的,但我这样做是为了进一步操作)

    2. 通过函数获取监听器路径:

      var thisPolyPath = globalLoadedPoly.getPath();
      
    3. 在加载的多边形发生变化时监听事件:

      google.maps.event.addListener(thisPolyPath, 'set_at', thisPolyHasChanged);
      google.maps.event.addListener(thisPolyPath, 'insert_at', thisPolyHasChanged);
      

    4.在函数thisPolyHasChanged()中,使用函数setSelection(shape)将加载的多边形设置为实际选择。并通过调用函数getCoordinatesOfLoadedPolygon获取坐标

    function thisPolyHasChanged()
    {
       // Setting the loaded poly as the new selection
       // Yes, it's global, so therefore not necessary to be sent
       // but like this way, it's more readable
       setSelection(globalLoadedPoly);
    
       // If you want to get the coordinates for saving
       // Calling the function getCoordinatesOfLoadedPolygon
       // For being more readable I send the global Object - yes, it's not necessary
       coordObj = getCoordinatesOfLoadedPolygon(globalLoadedPoly,'polygon');
       // do something with coordObj
       // ...
    }
    
      function setSelection(shape) 
      {
        // clearSelection is in the code I postet as the question 
        clearSelection();
        selectedShape = shape; // setting the loaded poly as the actual poly
        shape.setEditable(true); // making the loaded poly editable
        selectColor(shape.get('fillColor') || shape.get('strokeColor')); //setting the color
      }
    
    function getCoordinatesOfLoadedPolygon(getPolygon,shapeType)
    {
      // getLength is also a google-maps function / method
      var objSize = getPolygon.getPath().getLength();
      for (var i = 0; i < objSize; i++) 
      {
        // getArray is a google-maps function / method too
        var thisLat = getPolygon.getPath().getArray()[i].lat();
        var thisLng = getPolygon.getPath().getArray()[i].lng();
        coordObj[i]=new Object();
        coordObj[i]['lat']=thisLat;
        coordObj[i]['lng']=thisLng;
        coordObj[i]['shapeType']=shapeType;
      };
      return coordObj; 
    }
    

    最后,如果你迭代对象“coordObj”并在firebug中创建一个console.log,它看起来像这样:

     0 Object { lat=51.25572693191116, lng=9.136230200529099, shapeType="polygon"}
    
     1 Object { lat=51.80250070611026, lng=13.069335669279099, shapeType="polygon"}
    
     2 Object { lat=49.958995050387585, lng=10.476562231779099, shapeType="polygon"}
    

    结论:

    如果您想获取 google-maps 对象的坐标或其他属性,请使用专有的 google-maps 函数/方法:

    // For getting the coordinates you are generally working with:
    yourMapObject.getPath();
    //or
    yourMapObject.getPaths();
    
    // Getting especially the latitude:
    var latitude = yourMapObject.getPath().getArray()[i].lat();
    // Getting especially the longitude:
    var longitude = yourMapObject.getPath().getArray()[i].lng();
    
    // Getting the number of coordinates
    yourMapObject.getPath().getLength();
    

    不要忘记遍历整个对象,以获取所有坐标。

    解决方案代码可以真正优化。为了更易读,我分小步写了。

    我希望,我能够帮助任何人解决这个问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-02
      • 1970-01-01
      • 2022-01-07
      • 2012-07-10
      • 2012-11-28
      • 2013-11-23
      相关资源
      最近更新 更多