如何在Google地图上绘制圆圈时了解半径 [英] How to know radius while drawing a circle on Google Maps

查看:215
本文介绍了如何在Google地图上绘制圆圈时了解半径的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有什么:



根据Google的建议,我们使用了MVC对象和 DistanceWidget & RadiusWidget 显示半径,同时调整对现有圆圈(由DistanceWidget绘制的圆圈)正常工作的圆的大小。



小提琴演示



我需要:

我需要显示画一个新的圈子圈。事件 DistanceWidget & RadiusWidget 仅用于现有圆圈(由 DistanceWidget 绘制的圆圈)不适用于新圆圈(用户使用DrawingManager绘制的圆圈工具)。



是否可以显示DistanceWidget来创建新的圈子?

小提琴

解决方案

的确是一个很好的挑战。正如@DaveAlperovich所评论的那样,你不能使用 DrawingManager 来检索这条信息;在绘图时,您无法访问该圈子;您必须等待 DrawingManager 触发 circlecomplete 事件才能获得对此圆圈的引用。



不过,如果您不能拥有真正的管理员,那就假装它。
查看下面的代码段和描述。



var FakeDrawer = function(controlDiv,map){var self = this; / *初始化,一些样式... * / self._map = map; self.initControls(controlDiv); / *设置click事件侦听器:drawingmode为圆形控件* / google.maps.event.addDomListener(self._controls.circle,'click',function(){/ *确保一致性* / self.reset(); / *绑定绘图模式* / self._map.setOptions({draggableCursor:crosshair}); self._drawListener = self._map.addListener('mousedown',self.drawingMode(self));}); / *只需重置停止控件的东西* / google.maps.event.addDomListener(self._controls.stop,'click',function(){self.reset();});}; FakeDrawer.prototype.drawingMode =函数(self){return function(center){/ *让我们在绘制过程中冻结地图* / self._map.setOptions({draggable:false}); / *创建一个将被手动缩放的新圆圈* / var circle = new google.maps.Circle({fillColor:'#000',fillOpacity:0.3,strokeWeight:2,clickable:false,editable:false,map:self ._map,radius:1,center:center.latLng,zIndex:1}); / *更新每个鼠标移动的半径* / var onMouseMove = self._map.addListener('mousemove',function(border){var radius = 1000 * self.distanceBetweenPoints(center.latLng,border.latLng); circle.setRadius (radius); / *以下是该特性,绘制时知道半径* / google.maps.event.trigger(self,'drawing_radius_changed',circle);}); / *用户已完成绘图* / google.maps.event.addListenerOnce(self._map,'mouseup',function(){/ *移除所有侦听器,因为它们不再是必需的* / google.maps.event.removeListener (onMouseMove); circle.setEditable(true); / *恢复一些选项以保持一致的行为* / self.reset(); / *通知侦听器与最后一个圆圈* / google.maps.event.trigger(self,' circlecomplete',circle);}); };}; FakeDrawer.prototype.reset = function(){var self = this; self._map.setOptions({draggableCursor:,draggable:true}); / *删除任何应用的侦听器* / if(self._drawListener){google.maps.event.removeListener(self._drawListener); }}; / *创建视图和关联的css * / FakeDrawer.prototype.initControls = function(controlDiv){var self = this;函数createControlUI(title,image){var controlUI = document.createElement('div'); controlUI.style.backgroundColor ='#fff'; controlUI.style.border ='1px solid rgba(0,0,0,.15)'; controlUI.style.boxShadow ='1 4px -1px rgba(0,0,0,.3)'; controlUI.style.marginTop ='10px'; controlUI.style.textAlign ='center'; controlUI.style.width ='25px'; controlUI.style.height ='25px'; controlUI.style.display ='inline-block'; controlUI.title = title; if(image ==circle){controlUI.style.borderLeft =none; } var controlImgWrapper = document.createElement('div'); controlImgWrapper.style.width ='16px'; controlImgWrapper.style.height ='16px'; controlImgWrapper.style.overflow ='隐藏'; controlImgWrapper.style.display ='inline-block'; controlImgWrapper.style.marginTop ='4px'; controlUI.appendChild(controlImgWrapper); var imageOffset = {circle:0,openhand:-9 * 16} [image]; var controlImg = document.createElement('img'); controlImg.src ='https://maps.gstatic.com/mapfiles/drawing.png'; controlImg.style.marginTop = imageOffset +px; controlImgWrapper.appendChild(controlImg); var focusBackground = function(){controlUI.style.backgroundColor ='#eee'; }; var unfocusBackground = function(){controlUI.style.backgroundColor =#fff; }; controlImg.addEventListener('mouseenter',focusBackground); controlImg.addEventListener('mouseout',unfocusBackground); controlUI.addEventListener('mouseenter',focusBackground); controlUI.addEventListener('mouseout',unfocusBackground);返回controlUI; } self._controls = {circle:createControlUI(绘制一个圆圈,circle),停止:createControlUI(停止绘制,openhand),}; controlDiv.appendChild(self._controls.stop); controlDiv.appendChild(self._controls.circle);}; FakeDrawer.prototype.distanceBetweenPoints = function(p1,p2){if(!p1 ||!p2){return 0; } var R = 6371; var dLat =(p2.lat() - p1.lat())* Math.PI / 180; var dLon =(p2.lng() - p1.lng())* Math.PI / 180; Math.sin(dLat / 2)* Math.sin(dLat / 2)+ Math.cos(p1.lat()* Math.PI / 180)* Math.cos(p2.lat()* Math。 PI / 180)* Math.sin(dLon / 2)* Math.sin(dLon / 2); var c = 2 * Math.atan2(Math.sqrt(a),Math.sqrt(1 - a)); var d = R * c; return d;};函数InitializeMap(){var latlng = new google.maps.LatLng(29.760193,-95.36939); var myOptions = {zoom:12,center:latlng,zoomControl:true,mapTypeId:google.maps.MapTypeId.ROADMAP,disableDefaultUI:true}; var map = new google.maps.Map(document.getElementById(map),myOptions); / *添加自定义控件* / var fakeDrawerDiv = document.createElement('div'); var fakeDrawer = new FakeDrawer(fakeDrawerDiv,map); fakeDrawerDiv.index = 1; map.controls [google.maps.ControlPosition.TOP_CENTER] .push(fakeDrawerDiv); var updateInfo = function(circle){document.getElementById(info)。innerHTML =Radius:+ circle.getRadius(); }; google.maps.event.addListener(fakeDrawer,'drawing_radius_changed',updateInfo); google.maps.event.addListener(fakeDrawer'circlecomplete',function(circle){google.maps.event.addListener(circle,'radius_changed',function(){updateInfo(circle);});});} google .maps.event.addDomListener(window,'load',InitializeMap);

  html,body {height:100%; margin:0px; padding:0px} #map {height:80%; width:100%;}  

< script src = https://maps.googleapis.com/maps/api/js?v=3&libraries=drawing&ext=.js\"></script><div id =地图>< / div> ;< div id =info>< / div>


第1步:创建自定义控件



文件中的某处或作为外部库:

  var FakeDrawer = function(controlDiv,map){
var self = this;

/ *初始化,一些样式... * /
self._map = map;
self.initControls(controlDiv);
};

FakeDrawer.prototype.initControls(controlDiv){
var self = this;

function createControlUI(title,image){
var controlUI = document.createElement('div');
/ * ...查看片段的细节..只是一些样式* /
return controlUI;


self._controls = {
circle:createControlUI(绘制圆,圆),
stop:createControlUI(停止绘制, openhand),
};

controlDiv.appendChild(self._controls.stop);
controlDiv.appendChild(self._controls.circle);
};



步骤2:添加一些糖分

这是我们可能使用的功能; )



重置方法可在需要时恢复一致状态:

  FakeDrawer.prototype.reset = function(){
var self = this;
self._map.setOptions({
draggableCursor:,
draggable:true
});
$ b $ / *移除所有应用的监听器* /
if(self._drawListener){google.maps.event.removeListener(self._drawListener); }
};

而且,远程计算机:

 FakeDrawer.prototype.distanceBetweenPoints = function(p1,p2){
if(!p1 ||!p2){
return 0;
}
var R = 6371;
var dLat =(p2.lat() - p1.lat())* Math.PI / 180;
var dLon =(p2.lng() - p1.lng())* Math.PI / 180;
var a = Math.sin(dLat / 2)* Math.sin(dLat / 2)+ Math.cos(p1.lat()* Math.PI / 180)* Math.cos(p2.lat )* Math.PI / 180)* Math.sin(dLon / 2)* Math.sin(dLon / 2);
var c = 2 * Math.atan2(Math.sqrt(a),Math.sqrt(1 - a));
var d = R * c;
return d;
};



第3步:创建您自己的绘图模式



<现在我们有了一些控制,我们必须定义它们的行为。 stop 控制很简单,让我们看看控制。

  FakeDrawer.prototype。 drawingMode = function(self){
return function(center){
/ *让我们在绘制过程中冻结地图* /
self._map.setOptions({draggable:false});

/ *创建一个新的圈子,手动缩放* /
var circle = new google.maps.Circle({
fillColor:'#000',
fillOpacity:0.3,
strokeWeight:2,
clickable:false,
editable:false,
map:self._map,
radius:1,
center:center.latLng,
zIndex:1
});
$ b $ *更新每个鼠标移动的半径* /
var onMouseMove = self._map.addListener('mousemove',function(border){
var radius = 1000 * self.distanceBetweenPoints(center.latLng,border.latLng);
circle.setRadius(radius);

/ *以下是该功能,绘制时知道半径* /
google.maps.event.trigger(self,'drawing_radius_changed',circle);
});
$ b $ * / *用户已完成绘图* /
google.maps.event.addListenerOnce(self._map,'mouseup',function(){
/ *全部删除因为它们不再需要* /
google.maps.event.removeListener(onMouseMove);

circle.setEditable(true);

/ *还原一些选项保持一致的行为* /
self.reset();

/ *通知监听器与最终圈* /
google.maps.event.trigger(self ,'circlecplete',圈);
});
};
};



步骤4:绑定控制



现在确保一切正常,让我们在构造函数的初始版本中添加一些监听器,以便每个控件在单击时都有相应的操作。

  var FakeDrawer = function(controlDiv,map){
var self = this;

/ *初始化,一些样式... * /
self._map = map;
self.initControls(controlDiv);
$ b $ *设置点击事件侦听器:drawingmode * /
google.maps.event.addDomListener(self._controls.circle,'click',function(){
/ *确保一致性* /
self.reset();

/ *仅绘图模式* /
self._map.setOptions({draggableCursor:crosshair});
self._drawListener = self._map.addListener('mousedown',self.drawingMode(self));
});

google.maps.event.addDomListener(self._controls.stop,'click',function(){
self.reset();
});
};



步骤5:使用它!



假设您的地图已正确初始化。



在您的map init函数中:

  var fakeDrawerDiv = document。的createElement( 'DIV'); 
var fakeDrawer = new FakeDrawer(fakeDrawerDiv,map);

fakeDrawerDiv.index = 1;
map.controls [google.maps.ControlPosition.TOP_CENTER] .push(fakeDrawerDiv);
$ b $ var updateInfo = function(circle){
document.getElementById(info)。innerHTML =Radius:+ circle.getRadius();
};

google.maps.event.addListener(fakeDrawer,'drawing_radius_changed',updateInfo);
google.maps.event.addListener(fakeDrawer'circlecomplete',function(circle){
google.maps.event.addListener(circle,'radius_changed',function(){
updateInfo (圈);
});
});

享受,希望它会有所帮助。


What I have :

As per Google suggestion we have used MVC object and the events DistanceWidget & RadiusWidget to display the radius while re-sizing the circle which is working fine for existing circle (circle drawn by DistanceWidget).

Fiddle Demo

What I need :

I need to show the radius of the circle while drawing a new circle. The event DistanceWidget & RadiusWidget are used only for existing circle (circle drawn by DistanceWidget) not for new circle (user drawn circle by using DrawingManager tool).

Is it possible to show DistanceWidget for creating new circle?

Fiddle

解决方案

a nice challenge indeed. As @DaveAlperovich has commented, you can't use the DrawingManager to retrieve this piece of information; While drawing, you don't have any access to the circle; You have to wait for the DrawingManager to trigger the circlecomplete event to get a reference to this circle.

Nevertheless, if you can't have a real manager, just fake it. See the snippet and the description right below.

var FakeDrawer = function(controlDiv, map) {
  var self = this;

  /* Initialization, some styling ... */
  self._map = map;
  self.initControls(controlDiv);

  /* Setup the click event listener: drawingmode for the circle control */
  google.maps.event.addDomListener(self._controls.circle, 'click', function() {
    /* Ensure consistency */
    self.reset();

    /* Bind the drawing mode */
    self._map.setOptions({
      draggableCursor: "crosshair"
    });
    self._drawListener = self._map.addListener('mousedown', self.drawingMode(self));
  });

  /* Just reset things for the stop controls */
  google.maps.event.addDomListener(self._controls.stop, 'click', function() {
    self.reset();
  });
};

FakeDrawer.prototype.drawingMode = function(self) {
  return function(center) {
    /* Let's freeze the map during drawing */
    self._map.setOptions({
      draggable: false
    });

    /* Create a new circle which will be manually scaled */
    var circle = new google.maps.Circle({
      fillColor: '#000',
      fillOpacity: 0.3,
      strokeWeight: 2,
      clickable: false,
      editable: false,
      map: self._map,
      radius: 1,
      center: center.latLng,
      zIndex: 1
    });

    /* Update the radius on each mouse move */
    var onMouseMove = self._map.addListener('mousemove', function(border) {
      var radius = 1000 * self.distanceBetweenPoints(center.latLng, border.latLng);
      circle.setRadius(radius);

      /* Here is the feature, know the radius while drawing */
      google.maps.event.trigger(self, 'drawing_radius_changed', circle);
    });

    /* The user has finished its drawing */
    google.maps.event.addListenerOnce(self._map, 'mouseup', function() {
      /* Remove all listeners as they are no more required */
      google.maps.event.removeListener(onMouseMove);

      circle.setEditable(true);

      /* Restore some options to keep a consistent behavior */
      self.reset();

      /* Notify listener with the final circle */
      google.maps.event.trigger(self, 'circlecomplete', circle);
    });
  };
};

FakeDrawer.prototype.reset = function() {
  var self = this;

  self._map.setOptions({
    draggableCursor: "",
    draggable: "true"
  });

  /* Remove any applied listener */
  if (self._drawListener) {
    google.maps.event.removeListener(self._drawListener);
  }
};

/* Create views and associated css */
FakeDrawer.prototype.initControls = function(controlDiv) {
  var self = this;

  function createControlUI(title, image) {
    var controlUI = document.createElement('div');
    controlUI.style.backgroundColor = '#fff';
    controlUI.style.border = '1px solid rgba(0, 0, 0, .15)';
    controlUI.style.boxShadow = '1 4px -1px rgba(0, 0, 0, .3)';
    controlUI.style.marginTop = '10px';
    controlUI.style.textAlign = 'center';
    controlUI.style.width = '25px';
    controlUI.style.height = '25px';
    controlUI.style.display = 'inline-block';
    controlUI.title = title;
    if (image == "circle") {
      controlUI.style.borderLeft = "none";
    }

    var controlImgWrapper = document.createElement('div');
    controlImgWrapper.style.width = '16px';
    controlImgWrapper.style.height = '16px';
    controlImgWrapper.style.overflow = 'hidden';
    controlImgWrapper.style.display = 'inline-block';
    controlImgWrapper.style.marginTop = '4px';
    controlUI.appendChild(controlImgWrapper);

    var imageOffset = {
      "circle": 0,
      "openhand": -9 * 16
    }[image];

    var controlImg = document.createElement('img');
    controlImg.src = 'https://maps.gstatic.com/mapfiles/drawing.png';
    controlImg.style.marginTop = imageOffset + "px";
    controlImgWrapper.appendChild(controlImg);

    var focusBackground = function() {
      controlUI.style.backgroundColor = '#eee';
    };

    var unfocusBackground = function() {
      controlUI.style.backgroundColor = "#fff";
    };

    controlImg.addEventListener('mouseenter', focusBackground);
    controlImg.addEventListener('mouseout', unfocusBackground);
    controlUI.addEventListener('mouseenter', focusBackground);
    controlUI.addEventListener('mouseout', unfocusBackground);

    return controlUI;
  }

  self._controls = {
    circle: createControlUI("Draw a circle", "circle"),
    stop: createControlUI("Stop drawing", "openhand"),
  };

  controlDiv.appendChild(self._controls.stop);
  controlDiv.appendChild(self._controls.circle);
};

FakeDrawer.prototype.distanceBetweenPoints = function(p1, p2) {
  if (!p1 || !p2) {
    return 0;
  }
  var R = 6371;
  var dLat = (p2.lat() - p1.lat()) * Math.PI / 180;
  var dLon = (p2.lng() - p1.lng()) * Math.PI / 180;
  var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(p1.lat() * Math.PI / 180) * Math.cos(p2.lat() * Math.PI / 180) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  var d = R * c;
  return d;
};





function InitializeMap() {
  var latlng = new google.maps.LatLng(29.760193, -95.36939);
  var myOptions = {
    zoom: 12,
    center: latlng,
    zoomControl: true,
    mapTypeId: google.maps.MapTypeId.ROADMAP,
    disableDefaultUI: true
  };
  var map = new google.maps.Map(document.getElementById("map"), myOptions);

  /* Add a custom control */
  var fakeDrawerDiv = document.createElement('div');
  var fakeDrawer = new FakeDrawer(fakeDrawerDiv, map);

  fakeDrawerDiv.index = 1;
  map.controls[google.maps.ControlPosition.TOP_CENTER].push(fakeDrawerDiv);


  var updateInfo = function(circle) {
    document.getElementById("info").innerHTML = "Radius: " + circle.getRadius();
  };

  google.maps.event.addListener(fakeDrawer, 'drawing_radius_changed', updateInfo);
  google.maps.event.addListener(fakeDrawer, 'circlecomplete', function(circle) {
    google.maps.event.addListener(circle, 'radius_changed', function() {
      updateInfo(circle);
    });
  });
}


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

html,
body {
  height: 100%;
  margin: 0px;
  padding: 0px
}
#map {
  height: 80%;
  width: 100%;
}

<script src="https://maps.googleapis.com/maps/api/js?v=3&libraries=drawing&ext=.js"></script>
<div id="map"></div>
<div id="info"></div>

Step 1: Create a custom control

Somewhere in the file or as an external library:

var FakeDrawer = function (controlDiv, map) {
    var self = this;

    /* Initialization, some styling ... */
    self._map = map;
    self.initControls(controlDiv);
};

FakeDrawer.prototype.initControls(controlDiv) {
    var self = this;

    function createControlUI (title, image) {
        var controlUI = document.createElement('div');
        /* ... See the snippet for details .. just some styling */
        return controlUI;
    }

    self._controls = {
        circle: createControlUI("Draw a circle", "circle"),
        stop: createControlUI("Stop drawing", "openhand"),
     };

     controlDiv.appendChild(self._controls.stop);
     controlDiv.appendChild(self._controls.circle);
};

Step 2: Add some sugars

This are functions that we may use; Highly inspired from your JsFiddle :)

A reset method to recover a consistent state when needed:

FakeDrawer.prototype.reset = function () {
    var self = this;
    self._map.setOptions({
        draggableCursor: "",
        draggable: "true"
    });

    /* Remove any applied listener */
    if (self._drawListener) { google.maps.event.removeListener(self._drawListener) ; }
};

And, a distance computer:

FakeDrawer.prototype.distanceBetweenPoints = function (p1, p2) {
    if (!p1 || !p2) {
        return 0;
    }
    var R = 6371;
    var dLat = (p2.lat() - p1.lat()) * Math.PI / 180;
    var dLon = (p2.lng() - p1.lng()) * Math.PI / 180;
    var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(p1.lat() * Math.PI / 180) * Math.cos(p2.lat() * Math.PI / 180) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    var d = R * c;
    return d;
};

Step 3: Create your own drawing mode

Now that we have some controls, we have to define their behavior. The stop control is straightforward; Let's have a look to the circle control.

FakeDrawer.prototype.drawingMode = function (self) {
    return function (center) {
        /* Let's freeze the map during drawing */
        self._map.setOptions({draggable: false});

        /* Create a new circle which will be manually scaled */
        var circle = new google.maps.Circle({
            fillColor: '#000',
            fillOpacity: 0.3,
            strokeWeight: 2,
            clickable: false,
            editable: false,
            map: self._map,
            radius: 1,
            center: center.latLng,
            zIndex: 1
        });

        /* Update the radius on each mouse move */
        var onMouseMove = self._map.addListener('mousemove', function (border) {
            var radius = 1000 * self.distanceBetweenPoints(center.latLng, border.latLng);
            circle.setRadius(radius);

            /* Here is the feature, know the radius while drawing */
            google.maps.event.trigger(self, 'drawing_radius_changed', circle);
        });

        /* The user has finished its drawing */
        google.maps.event.addListenerOnce(self._map, 'mouseup', function () {
            /* Remove all listeners as they are no more required */
            google.maps.event.removeListener(onMouseMove);

            circle.setEditable(true);

            /* Restore some options to keep a consistent behavior */
            self.reset();

            /* Notify listener with the final circle */
            google.maps.event.trigger(self, 'circlecomplete', circle);
        });
    };
};

Step 4: Bind controls

Now that everything is okay, let's add some listeners to the initial version of the constructor so that each control has a corresponding action when clicked.

var FakeDrawer = function (controlDiv, map) {
    var self = this;

    /* Initialization, some styling ... */
    self._map = map;
    self.initControls(controlDiv);

    /* Setup the click event listeners: drawingmode */
    google.maps.event.addDomListener(self._controls.circle, 'click', function() {
        /* Ensure consistency */
        self.reset();

        /* Only drawingmode */
        self._map.setOptions({draggableCursor: "crosshair"});
        self._drawListener = self._map.addListener('mousedown', self.drawingMode(self));
    });

    google.maps.event.addDomListener(self._controls.stop, 'click', function () {
        self.reset();
    });
};

Step 5: Use it!

Assuming that your map has been initialized correctly.

Inside your map init function:

var fakeDrawerDiv = document.createElement('div');
var fakeDrawer = new FakeDrawer(fakeDrawerDiv, map);

fakeDrawerDiv.index = 1;
map.controls[google.maps.ControlPosition.TOP_CENTER].push(fakeDrawerDiv);

var updateInfo = function (circle) {
    document.getElementById("info").innerHTML = "Radius: " + circle.getRadius();
};

google.maps.event.addListener(fakeDrawer, 'drawing_radius_changed', updateInfo);
google.maps.event.addListener(fakeDrawer, 'circlecomplete', function (circle) {
    google.maps.event.addListener(circle, 'radius_changed', function () {
        updateInfo(circle);
    });
});

Enjoy, hope it will help.

这篇关于如何在Google地图上绘制圆圈时了解半径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆