Google Maps v3 setting a circle with editable radius but not center

前端 未结 2 598
情深已故
情深已故 2021-01-02 17:43

I have managed to put a circle on a map and make it editable:

var circle = new google.maps.Circle({
          map: map,
          radius: 1609.344, // 1 mile         


        
相关标签:
2条回答
  • 2021-01-02 18:06

    You can try listening for the center_changed event and when it fires reposition the center, for example:

    Global variables:

        var centerPoint = new G.LatLng(45.5, -100.5);
        var ignore = false;
        var poly;
    //position the map where the circle is so we can see it.
        map.setCenter(centerPoint);
        map.setZoom(11);
    

    and then:

    poly = new google.maps.Circle({
        map: map,
        center:centerPoint,
        radius: 1609.344, // 1 mile
        editable: true,
        fillOpacity: 0.25
    });
    
    G.event.addListener(poly,'center_changed',function(){
        if (ignore){
            ignore = false;
            return;
        }
        poly.setEditable(false);
        ignore = true;
        poly.setCenter(centerPoint);
        poly.setEditable(true);
    });
    

    The only problem is that the center marker may be misleading to the user.

    0 讨论(0)
  • 2021-01-02 18:15

    See this article from the documentation (before editable objects). If you take the step 6 and don't make the center marker draggable, I think it is what you want.

    fiddle containing original code from link

    code snippet:

    /**
     * A distance widget that will display a circle that can be resized and will
     * provide the radius in km.
     *
     * @param {google.maps.Map} map The map to attach to.
     *
     * @constructor
     */
    function DistanceWidget(map) {
      this.set('map', map);
      this.set('position', map.getCenter());
    
      var marker = new google.maps.Marker({
        // draggable: true,  // <-- change to make so position doesn't move
        title: 'Move me!'
      });
    
      // Bind the marker map property to the DistanceWidget map property
      marker.bindTo('map', this);
    
      // Bind the marker position property to the DistanceWidget position
      // property
      marker.bindTo('position', this);
    
      // Create a new radius widget
      var radiusWidget = new RadiusWidget();
    
      // Bind the radiusWidget map to the DistanceWidget map
      radiusWidget.bindTo('map', this);
    
      // Bind the radiusWidget center to the DistanceWidget position
      radiusWidget.bindTo('center', this, 'position');
    
      // Bind to the radiusWidgets' distance property
      this.bindTo('distance', radiusWidget);
    
      // Bind to the radiusWidgets' bounds property
      this.bindTo('bounds', radiusWidget);
    }
    DistanceWidget.prototype = new google.maps.MVCObject();
    
    
    /**
     * A radius widget that add a circle to a map and centers on a marker.
     *
     * @constructor
     */
    function RadiusWidget() {
      var circle = new google.maps.Circle({
        strokeWeight: 2
      });
    
      // Set the distance property value, default to 10km.
      this.set('distance', 10);
    
      // Bind the RadiusWidget bounds property to the circle bounds property.
      this.bindTo('bounds', circle);
    
      // Bind the circle center to the RadiusWidget center property
      circle.bindTo('center', this);
    
      // Bind the circle map to the RadiusWidget map
      circle.bindTo('map', this);
    
      // Bind the circle radius property to the RadiusWidget radius property
      circle.bindTo('radius', this);
    
      // Add the sizer marker
      this.addSizer_();
    }
    RadiusWidget.prototype = new google.maps.MVCObject();
    
    
    /**
     * Update the radius when the distance has changed.
     */
    RadiusWidget.prototype.distance_changed = function() {
      this.set('radius', this.get('distance') * 1000);
    };
    
    
    /**
     * Add the sizer marker to the map.
     *
     * @private
     */
    RadiusWidget.prototype.addSizer_ = function() {
      var sizer = new google.maps.Marker({
        draggable: true,
        title: 'Drag me!'
      });
    
      sizer.bindTo('map', this);
      sizer.bindTo('position', this, 'sizer_position');
    
      var me = this;
      google.maps.event.addListener(sizer, 'drag', function() {
        // As the sizer is being dragged, its position changes.  Because the
        // RadiusWidget's sizer_position is bound to the sizer's position, it will
        // change as well.
        var min = 0.5;
        var max = 15;
        var pos = me.get('sizer_position');
        var center = me.get('center');
        var distance = google.maps.geometry.spherical.computeDistanceBetween(center, pos) / 1000;
        if (distance < min) {
          me.set('sizer_position', google.maps.geometry.spherical.computeOffset(center, min * 1000, google.maps.geometry.spherical.computeHeading(center, pos)));
        } else if (distance > max) {
          me.set('sizer_position', google.maps.geometry.spherical.computeOffset(center, max * 1000, google.maps.geometry.spherical.computeHeading(center, pos)));
        }
        // Set the circle distance (radius)
        me.setDistance();
      });
    };
    
    
    /**
     * Update the center of the circle and position the sizer back on the line.
     *
     * Position is bound to the DistanceWidget so this is expected to change when
     * the position of the distance widget is changed.
     */
    RadiusWidget.prototype.center_changed = function() {
      var bounds = this.get('bounds');
    
      // Bounds might not always be set so check that it exists first.
      if (bounds) {
        var lng = bounds.getNorthEast().lng();
    
        // Put the sizer at center, right on the circle.
        var position = new google.maps.LatLng(this.get('center').lat(), lng);
        this.set('sizer_position', position);
      }
    };
    
    
    /**
     * Set the distance of the circle based on the position of the sizer.
     */
    RadiusWidget.prototype.setDistance = function() {
      // As the sizer is being dragged, its position changes.  Because the
      // RadiusWidget's sizer_position is bound to the sizer's position, it will
      // change as well.
      var pos = this.get('sizer_position');
      var center = this.get('center');
      var distance = google.maps.geometry.spherical.computeDistanceBetween(center, pos) / 1000;
    
      // Set the distance property for any objects that are bound to it
      this.set('distance', distance);
    };
    
    
    function init() {
      var mapDiv = document.getElementById('map-canvas');
      var map = new google.maps.Map(mapDiv, {
        center: new google.maps.LatLng(37.790234970864, -122.39031314844),
        zoom: 11,
        mapTypeId: google.maps.MapTypeId.ROADMAP
      });
      var distanceWidget = new DistanceWidget(map);
    
      google.maps.event.addListener(distanceWidget, 'distance_changed', function() {
        displayInfo(distanceWidget);
      });
    
      google.maps.event.addListener(distanceWidget, 'position_changed', function() {
        displayInfo(distanceWidget);
      });
    }
    
    function displayInfo(widget) {
      var info = document.getElementById('info');
      info.innerHTML = 'Position: ' + widget.get('position') + ', distance: ' +
        widget.get('distance');
    }
    
    google.maps.event.addDomListener(window, 'load', init);
    #map-canvas {
      height: 500px;
    }
    <script src="https://maps.googleapis.com/maps/api/js?libraries=geometry"></script>
    <div id="info"></div>
    <div id="map-canvas"></div>

    original article (link now dead)

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