31

描画マネージャを使用する(そして選択可能な形状を実装する)マッピングアプリケーションを作成しました。プログラムは次のように機能します。ボタンをクリックしてポリゴンの描画が終了すると、パスがポリゴンにマッピングされます。

このプロセスの後でポリゴンを編集するときに、マッピング関数を再度呼び出す必要があります。ただし、この部分を機能させることはできません。

次のコードを使用してみましたが、このリスナーを追加するとシェイプがまだ選択されていないため、常にエラーが発生します。私に何ができる?

google.maps.event.addListener(selectedShape, 'set_at', function() {
    console.log("test");
});

google.maps.event.addListener(selectedShape, 'insert_at', function() {
    console.log("test");
});

重要なコード:

function showDrawingManager(){
    var managerOptions = {
        drawingControl: true,
        drawingControlOptions: {
            position: google.maps.ControlPosition.TOP_CENTER,
            drawingModes: [google.maps.drawing.OverlayType.MARKER, google.maps.drawing.OverlayType.POLYLINE, google.maps.drawing.OverlayType.POLYGON]
        },
        markerOptions: {
            editable: true,
            icon: '/largeTDGreenIcons/blank.png'
        },
        polygonOptions: {
            fillColor: "#1E90FF",
            strokeColor: "#1E90FF",
        },
        polylineOptions: {
            strokeColor: "#FF273A"
        }
    }

    var drawingManager = new google.maps.drawing.DrawingManager(managerOptions);
    drawingManager.setMap(map);
    return drawingManager;
}

function clearSelection() {
    if (selectedShape) {
        console.log("clearSelection");

        selectedShape.setEditable(false);
        selectedShape = null;
        numberOfShapes--;
    }
}

function setSelection(shape) {

   console.log("setSelection");

   clearSelection();
   selectedShape = shape;
   shape.setEditable(true);
   numberOfShapes++;
   //getInformation(shape);
}

function initialize(){

    //....

    var drawingManager = showDrawingManager();
    google.maps.event.addListener(drawingManager, 'overlaycomplete', function(e) {
        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);
        }
    });
4

5 に答える 5

32

.getPath()を呼び出し、図形がクリックされるたびに呼び出されるリスナーの中にリスナーを配置することで、これを解決しました。Google APIのドキュメントでは、set_atの使用方法があまり明確ではないため、他の人にも役立つ可能性があります。

// 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() {
    google.maps.event.addListener(newShape.getPath(), 'set_at', function() {
        console.log("test");
    });

    google.maps.event.addListener(newShape.getPath(), 'insert_at', function() {
        console.log("test");
    });
    setSelection(newShape);
});
于 2012-09-20T16:37:05.477 に答える
21
    google.maps.event.addListener(yourPolygon.getPath(), 'insert_at', function(index, obj) {
           //polygon object: yourPolygon
    });
    google.maps.event.addListener(yourPolygon.getPath(), 'set_at', function(index, obj) {
           //polygon object: yourPolygon
    });

上記のコードは私のために働いています。ハイset_atライトされたドット(エッジ)からポリゴン領域を変更すると発生し、ハイライトされたinsert_atエッジの間にあるポイントをドラッグすると発生します。

polygoncompleteイベントで、データベースからポリゴンをロードした後に使用しました。それは彼らのためにうまく働いています。

于 2013-12-19T12:46:38.990 に答える
10

set_atとドラッグに関する問題を回避するために、以下を追加しました。これにより、図面がドラッグされているときにset_atのイベントブロードキャストが無効になります。ポリゴンクラスを拡張するクラスを作成し、次のメソッドを追加しました。

 ExtDrawingPolygon.prototype.enableCoordinatesChangedEvent = function(){
  var me = this,
      superClass = me.superClass,
      isBeingDragged = false,
      triggerCoordinatesChanged = function(){
         //broadcast normalized event
         google.maps.event.trigger(superClass, 'coordinates_changed');
      };

  // If the overlay is being dragged, set_at gets called repeatedly,
  // so either we can debounce that or ignore while dragging,
  // ignoring is more efficient.
  google.maps.event.addListener(superClass, 'dragstart', function(){
    isBeingDragged = true;
  });

  // If the overlay is dragged
  google.maps.event.addListener(superClass, 'dragend', function(){
    triggerCoordinatesChanged();
    isBeingDragged = false;
  });

  // Or vertices are added to any of the possible paths, or deleted
  var paths = superClass.getPaths();
  paths.forEach(function(path, i){
    google.maps.event.addListener(path, "insert_at", function(){
      triggerCoordinatesChanged();
    });
    google.maps.event.addListener(path, "set_at", function(){
      if(!isBeingDragged){
        triggerCoordinatesChanged();
      }
    });
    google.maps.event.addListener(path, "remove_at", function(){
      triggerCoordinatesChanged();
    });
  });
};

ポリゴン自体に「coordinates_changed」イベントが追加されたため、他のコードは、単純化された1つの優れたイベントをリッスンできます。

于 2015-11-17T22:07:38.663 に答える
3

chrismarxの答えから始めて、以下はTypeScriptで新しいイベントを使用する例です。未定義の参照に問題があったため、スーパークラスを削除し、「me」への参照を変更するという小さな変更を行いました。

ファイルやグローバル構成ファイルなどの先頭で、次を使用します。

declare global {
    module google.maps {
        interface Polygon {
            enableCoordinatesChangedEvent();
        }
    }
}

次に、拡張子を定義します。

google.maps.Polygon.prototype.enableCoordinatesChangedEvent = function () {

    var me = this,
        isBeingDragged = false,
        triggerCoordinatesChanged = function () {
            // Broadcast normalized event
            google.maps.event.trigger(me, 'coordinates_changed');
        };

    // If  the overlay is being dragged, set_at gets called repeatedly,
    // so either we can debounce that or igore while dragging,
    // ignoring is more efficient
    google.maps.event.addListener(me, 'dragstart', function () {
        isBeingDragged = true;
    });

    // If the overlay is dragged
    google.maps.event.addListener(me, 'dragend', function () {
        triggerCoordinatesChanged();
        isBeingDragged = false;
    });

    // Or vertices are added to any of the possible paths, or deleted
    var paths = me.getPaths();
    paths.forEach(function (path, i) {
        google.maps.event.addListener(path, "insert_at", function () {
            triggerCoordinatesChanged();
        });
        google.maps.event.addListener(path, "set_at", function () {
            if (!isBeingDragged) {
                triggerCoordinatesChanged();
            }
        });
        google.maps.event.addListener(path, "remove_at", function () {
            triggerCoordinatesChanged();
        });
    });
};

最後に拡張機能を呼び出し、リスナーを追加します。

  google.maps.event.addListener(drawingManager, 'overlaycomplete', function (event) {
        event.overlay.enableCoordinatesChangedEvent();

        google.maps.event.addListener(event.overlay, 'coordinates_changed', function (index, obj) {
            // Polygon object: yourPolygon
            console.log('coordinates_changed');
        });
    });
于 2016-11-03T09:49:04.513 に答える
0

Thomasの回答から始めて、GeoJSONから追加さDrawingManagerれたsだけでなく、で作成されたオーバーレイの編集を可能にする実装を次に示します。Feature

私にとっての主な苦労は、によって作成された同様の名前のタイプと一緒にgoogle.maps作成された-prefixedオーバーレイタイプを使用することでした。最終的には、組み込みオブジェクトを無視して、すべてを再作成されたオーバーレイとして保存し、編集イベントリスナーを設定して、描画時に個別に呼び出しました。最初に描画されたオーバーレイとロードされたフィーチャは破棄されます。DrawingManagergoogle.maps.Data FeatureaddFromGeoJson()DatasetMap()

プロセスは次のようになります。

  1. マップを初期化します。
  2. addfeature機能が追加されるたびに検出するイベントリスナーを追加します。これはaddGeoJson()、それぞれFeatureの間に発生し、対応するオーバーレイタイプとジオメトリを取得し、それらをユーティリティ関数に渡してaddFeature()オーバーレイを作成します。
  3. GeoJSONをロードします。これにより、ロードされたすべてのオブジェクトに対して上記のイベントリスナーが起動されます。
  4. を初期化しDrawingManagerます。
  5. オーバーレイのタイプ( 、、、および){overlay}completeごとにイベントリスナーを追加します。発生すると、これらのイベントは最初にオーバーレイが有効かどうかを判断し(たとえば、ポリゴンに3つ以上の頂点がある)、次に呼び出して、オーバーレイのタイプとジオメトリを渡します。polygonpolylinemarkeraddFeature()

呼び出されると、addFeature()オーバーレイが再作成され、該当するすべてのイベントリスナーが設定されます。最後に、オーバーレイが配列に保存され、マップに表示されます。

// GeoJSON containing previously stored data (optional) 
var imported = {
  type: "FeatureCollection",
  features: [{
    "type": "Feature",
    "geometry": {
      "type": "Point",
      "coordinates": [
        -73.985603, 40.748429
      ],
    },
    properties: {
      activity: "Entry",
    }
  }, ]
};

// this will fill with map data as you import it from geojson or draw
var features = {
  polygons: [],
  lines: [],
  markers: []
};

// set default drawing styles
var styles = {
  polygon: {
    fillColor: '#00ff80',
    fillOpacity: 0.3,
    strokeColor: '#008840',
    strokeWeight: 1,
    clickable: true,
    editable: true,
    zIndex: 1
  },
  polyline: {
    strokeColor: '#ffff00',
    strokeWeight: 3,
    clickable: true,
    editable: true,
    zIndex: 2
  },
  marker: {
    clickable: true,
    draggable: true,
    zIndex: 3
  }
}

var map;

function initMap() {
  map = new google.maps.Map(document.getElementById('map'), {
    center: {
      lat: 40.748429,
      lng: -73.985603
    },
    zoom: 18,
    noClear: true,
    mapTypeId: 'satellite',
    navigationControl: true,
    mapTypeControl: false,
    streetViewControl: false,
    tilt: 0
  });

  // add this listener BEFORE loading from GeoJSON
  map.data.addListener('addfeature', featureAdded);

  // load map features from geojson
  map.data.addGeoJson(imported);

  // initialize drawing tools
  var drawingManager = new google.maps.drawing.DrawingManager({
    // uncomment below line to set default drawing mode
    // drawingMode: 'marker',  
    drawingControl: true,
    drawingControlOptions: {
      position: google.maps.ControlPosition.TOP_CENTER,
      drawingModes: ['polygon', 'polyline', 'marker']
    },
    polygonOptions: styles.polygon,
    polylineOptions: styles.polyline,
    markerOptions: styles.marker
  });
  drawingManager.setMap(map);

  // for each drawing mode, set a listener for end of drawing
  drawingManager.addListener('polygoncomplete', function(polygon) {
    // delete drawing if doesn't have enough points
    if (polygon.getPath().getLength() < 3) {
      alert('Polygons must have 3 or more points.');
      polygon.getPath().clear();
    }
    // otherwise create new feature and delete drawing
    else {
      addFeature('Polygon', polygon.getPath());
      polygon.setMap(null);
    }
  });
  drawingManager.addListener('polylinecomplete', function(line) {
    // delete drawing if doesn't have enough points
    if (line.getPath().getLength() < 2) {
      alert('Lines must have 2 or more points.');
      line.getPath().clear();
    }
    // otherwise create new feature and delete drawing
    else {
      addFeature('Polyline', line.getPath());
      line.setMap(null);
    }
  });
  drawingManager.addListener('markercomplete', function(marker) {
    // point geometries have only one point by definition, 
    // so create new feature and delete drawing
    addFeature('Point', marker.getPosition());
    marker.setMap(null);
    updateGeoJSON();
  });
}

// this function gets called when GeoJSON gets loaded
function featureAdded(e) {
  switch (e.feature.getGeometry().getType()) {
    case 'Polygon':
      addFeature('Polygon', e.feature.getGeometry().getAt(0).getArray());
      break;
    case 'LineString':
      addFeature('Polyline', e.feature.getGeometry().getArray());
      break;
    case 'Point':
      addFeature('Point', e.feature.getGeometry().get());
  }
  map.data.remove(e.feature);
}

function addFeature(type, path) {
  switch (type) {
    case 'Polygon':
      var polygon = new google.maps.Polygon(styles.polygon);
      polygon.setPath(path);

      // listeners for detecting geometry changes
      polygon.getPath().addListener('insert_at', someFunction)
      polygon.getPath().addListener('set_at', someFunction);
      polygon.getPath().addListener('remove_at', someFunction);
      polygon.getPath().addListener('dragend', someFunction);

      // delete vertex using right click
      polygon.addListener('rightclick', function(e) {
        if (e.vertex == undefined) return;
        if (polygon.getPath().getLength() == 3) {
          polygon.setMap(null);
          features.polygons = features.polygons.filter(isValid);
        } else {
          polygon.getPath().removeAt(e.vertex);
          outputAsGeoJSON();
        }
      });

      // add it to our list of features
      features.polygons.push(polygon);

      // and display it on the map
      polygon.setMap(map);
      break;

    case 'Polyline':
      var line = new google.maps.Polyline(styles.polyline);
      line.setPath(path);

      line.getPath().addListener('insert_at', someOtherFunction);
      line.getPath().addListener('set_at', someOtherFunction);
      line.getPath().addListener('remove_at', someOtherFunction);
      line.getPath().addListener('dragend', someOtherFunction);

      // allow right-click vertex deletion
      line.addListener('rightclick', function(e) {
        if (e.vertex == undefined) return;
        if (line.getPath().getLength() == 2) {
          line.setMap(null);
          features.lines = features.lines.filter(isValid);
        } else {
          line.getPath().removeAt(e.vertex);
          outputAsGeoJSON();
        }
      });

      // add it to our list of features
      features.lines.push(line);

      // and display it on the map
      line.setMap(map);
      break;

    case 'Point':
      var marker = new google.maps.Marker(styles.marker);
      marker.setPosition(path);

      // make a splashy entrance
      marker.setAnimation(google.maps.Animation.DROP);

      // detect modifications
      marker.addListener('drag', function(e) {
        // unnecessary bouncing just to throw you off
        marker.setAnimation(google.maps.Animation.BOUNCE);
      });
      marker.addListener('dragend', function(e) {
        // make the bouncing stop
        marker.setAnimation(null);
      })

      // allow right-click deletion
      marker.addListener('rightclick', function(e) {
        marker.setMap(null);
        features.markers = features.markers.filter(isValid);
        outputAsGeoJSON();
      });

      // add it to our list of features
      features.markers.push(marker);

      // and display it on the map
      marker.setMap(map);
      break;
  }

  outputAsGeoJSON();
}

function someFunction() {
  // do stuff
}

function someOtherFunction() {
  // do other stuff
}

// utility function for reuse any time someone right clicks
function isValid(f) {
  return f.getMap() != null;
}

function outputAsGeoJSON() {
  // we're only using the Data type here because it can export as GeoJSON
  var data = new google.maps.Data;

  // add all the polygons in our list of features
  features.polygons.forEach(function(polygon, i) {
    data.add({
      geometry: new google.maps.Data.Polygon([polygon.getPath().getArray()]),
      properties: {
        description: 'I am a polygon'
      }
    });
  });

  // and add all the lines 
  features.lines.forEach(function(line, i) {
    data.add({
      geometry: new google.maps.Data.LineString(line.getPath().getArray()),
      properties: {
        description: 'I am a line'
      }
    });
  });

  // and finally any markers
  features.markers.forEach(function(marker, i) {
    data.add({
      geometry: new google.maps.Data.Point(marker.getPosition()),
      properties: {
        description: 'I am a marker'
      }
    });
  });

  // GeoJSONify it
  data.toGeoJson(function(json) {
    document.getElementById('geojson').value = JSON.stringify(json);
  });
}

https://jsfiddle.net/pqdu05s9/1/

于 2019-04-03T03:11:53.337 に答える