javascript – 多个圆圈 – >一个多边形?

前端之家收集整理的这篇文章主要介绍了javascript – 多个圆圈 – >一个多边形?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
使用Google Maps API v3,我可以在地图上创建多个google.maps.Circle对象.但是,我现在需要以某种方式“连接”它们.我有以下带有多个圆圈的地图:

我现在需要让它看起来像这样:

Correct map http://www.pcwp.com/images2009/ui-2.gif

我在互联网上寻找解决方案,但无济于事.有任何想法吗?

解决方法

您可能需要考虑通过在x间隔添加附加圆来解决此问题,并在路径的每个点之间增加半径.这将非常容易实施,并适用于旋风的任何方向.显然 Matti’s suggested solution通过连接所有切线来创建多边形会更准确,但您可以将此视为可能的替代方案.主要的缺点是它可能需要一些努力使它看起来很漂亮,并且它显然会使用比你渲染单个多边形更多的客户端资源.

让我们从重新创建地图开始:

<!DOCTYPE html>
<html> 
<head> 
   <Meta http-equiv="content-type" content="text/html; charset=UTF-8"/> 
   <title>Google Maps Cyclones</title> 
   <script src="http://maps.google.com/maps/api/js?sensor=false" 
           type="text/javascript"></script> 
</head> 
<body> 
   <div id="map" style="width: 600px; height: 400px"></div> 

   <script type="text/javascript"> 
      var i;

      var mapOptions = { 
         mapTypeId: google.maps.MapTypeId.TERRAIN,center: new google.maps.LatLng(28.50,-81.50),zoom: 5
      };

      var map = new google.maps.Map(document.getElementById("map"),mapOptions);

      var pathPoints = [
         new google.maps.LatLng(25.48,-71.26),new google.maps.LatLng(25.38,-73.70),new google.maps.LatLng(25.28,-77.00),new google.maps.LatLng(25.24,-80.11),new google.maps.LatLng(25.94,-82.71),new google.maps.LatLng(27.70,-87.14)
      ];

      pathPoints[0].radius = 80;
      pathPoints[1].radius = 100;
      pathPoints[2].radius = 200;
      pathPoints[3].radius = 300;
      pathPoints[4].radius = 350;
      pathPoints[5].radius = 550;

      new google.maps.Polyline({
         path: pathPoints,strokeColor: '#00FF00',strokeOpacity: 1.0,strokeWeight: 3,map: map
      });

      for (i = 0; i < pathPoints.length; i++) {
         new google.maps.Circle({
            center: pathPoints[i],radius: pathPoints[i].radius * 1000,fillColor: '#FF0000',fillOpacity: 0.2,strokeOpacity: 0.5,strokeWeight: 1,map: map
         });
      }

   </script> 
</body> 
</html>

Google Maps Cyclones – Figure 1 http://img186.imageshack.us/img186/1197/mp1h.png

我假设你已经到了这一点,因此上面的例子应该是不言自明的.基本上我们已经定义了6个点,以及6个半径,并且我们已经在地图上渲染了圆圈以及绿色路径.

在我们继续之前,我们需要定义一些方法来计算从一个点到另一个点的距离和方位.我们还需要一种方法,在给定方位时返回目标点,以及从源点移动的距离.幸运的是,Chris Veness于Calculate distance,bearing and more between Latitude/Longitude points为这些方法提供了非常好的JavaScript实现.以下方法已经过调整,可以与Google的google.maps.LatLng一起使用:

Number.prototype.toRad = function() {
   return this * Math.PI / 180;
}

Number.prototype.toDeg = function() {
   return this * 180 / Math.PI;
}

google.maps.LatLng.prototype.destinationPoint = function(brng,dist) {
   dist = dist / 6371;  
   brng = brng.toRad();  
   var lat1 = this.lat().toRad(),lon1 = this.lng().toRad();

   var lat2 = Math.asin( Math.sin(lat1)*Math.cos(dist) + 
                         Math.cos(lat1)*Math.sin(dist)*Math.cos(brng) );
   var lon2 = lon1 + Math.atan2(Math.sin(brng)*Math.sin(dist)*Math.cos(lat1),Math.cos(dist)-Math.sin(lat1)*Math.sin(lat2));

   if (isNaN(lat2) || isNaN(lon2)) return null;
   return new google.maps.LatLng(lat2.toDeg(),lon2.toDeg());
}

google.maps.LatLng.prototype.bearingTo = function(point) {
   var lat1 = this.lat().toRad(),lat2 = point.lat().toRad();
   var dLon = (point.lng()-this.lng()).toRad();

   var y = Math.sin(dLon) * Math.cos(lat2);
   var x = Math.cos(lat1)*Math.sin(lat2) -
           Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon);

   var brng = Math.atan2(y,x);

   return ((brng.toDeg()+360) % 360);
}

google.maps.LatLng.prototype.distanceTo = function(point) {
   var lat1 = this.lat().toRad(),lon1 = this.lng().toRad();
   var lat2 = point.lat().toRad(),lon2 = point.lng().toRad();
   var dLat = lat2 - lat1;
   var dLon = lon2 - lon1;

   var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
           Math.cos(lat1) * Math.cos(lat2) * 
           Math.sin(dLon/2) * Math.sin(dLon/2);

   return 6371 * (2 * Math.atan2(Math.sqrt(a),Math.sqrt(1-a)));
}

然后我们需要添加另一个循环,该循环将我们之前用于渲染原始圆的for循环内的中间圆渲染.以下是它的实现方式:

var distanceStep = 50;    // Render an intermediate circle every 50km.

for (i = 0; i < pathPoints.length; i++) {
   new google.maps.Circle({
      center: pathPoints[i],map: map
   });

   if (i < (pathPoints.length - 1)) {
      distanceToNextPoint = pathPoints[i].distanceTo(pathPoints[i + 1]);
      bearingToNextPoint = pathPoints[i].bearingTo(pathPoints[i + 1]);
      radius = pathPoints[i].radius;
      radiusIncrement = (pathPoints[i + 1].radius - radius) / 
                        (distanceToNextPoint / distanceStep);

      for (j = distanceStep; 
           j < distanceToNextPoint; 
           j += distanceStep,radius += radiusIncrement) {

         new google.maps.Circle({
            center: pathPoints[i].destinationPoint(bearingToNextPoint,j),radius: radius * 1000,strokeWeight: 0,map: map
         });
      }
   }
}

这就是我们得到的:

Google Maps Cyclones – Figure 2 http://img188.imageshack.us/img188/5687/mp2a.png

如果没有原始圆圈周围的黑色笔划,这就是它的样子:

Google Maps Cyclones – Figure 3 http://img181.imageshack.us/img181/2908/mp3t.png

您可能会注意到,主要的挑战是渲染具有一致不透明度的圆圈,即使它们彼此重叠.有几种方法可以实现这一目标,但这可能是另一个问题的主题.

在任何情况下,以下是此示例的完整实现:

<!DOCTYPE html>
<html> 
<head> 
   <Meta http-equiv="content-type" content="text/html; charset=UTF-8"/> 
   <title>Google Maps Cyclones</title> 
   <script src="http://maps.google.com/maps/api/js?sensor=false" 
           type="text/javascript"></script> 
</head> 
<body> 
   <div id="map" style="width: 600px; height: 400px"></div> 

   <script type="text/javascript"> 
      Number.prototype.toRad = function() {
         return this * Math.PI / 180;
      }

      Number.prototype.toDeg = function() {
         return this * 180 / Math.PI;
      }

      google.maps.LatLng.prototype.destinationPoint = function(brng,dist) {
         dist = dist / 6371;  
         brng = brng.toRad();  
         var lat1 = this.lat().toRad(),lon1 = this.lng().toRad();

         var lat2 = Math.asin( Math.sin(lat1)*Math.cos(dist) + 
                               Math.cos(lat1)*Math.sin(dist)*Math.cos(brng) );
         var lon2 = lon1 + Math.atan2(Math.sin(brng)*Math.sin(dist)*Math.cos(lat1),Math.cos(dist)-Math.sin(lat1)*Math.sin(lat2));

         if (isNaN(lat2) || isNaN(lon2)) return null;
         return new google.maps.LatLng(lat2.toDeg(),lon2.toDeg());
      }

      google.maps.LatLng.prototype.bearingTo = function(point) {
         var lat1 = this.lat().toRad(),lat2 = point.lat().toRad();
         var dLon = (point.lng()-this.lng()).toRad();

         var y = Math.sin(dLon) * Math.cos(lat2);
         var x = Math.cos(lat1)*Math.sin(lat2) -
                 Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon);

         var brng = Math.atan2(y,x);

         return ((brng.toDeg()+360) % 360);
      }

      google.maps.LatLng.prototype.distanceTo = function(point) {
         var lat1 = this.lat().toRad(),lon1 = this.lng().toRad();
         var lat2 = point.lat().toRad(),lon2 = point.lng().toRad();
         var dLat = lat2 - lat1;
         var dLon = lon2 - lon1;

         var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
                 Math.cos(lat1) * Math.cos(lat2) * 
                 Math.sin(dLon/2) * Math.sin(dLon/2);

         return 6371 * (2 * Math.atan2(Math.sqrt(a),Math.sqrt(1-a)));
      }

      var i;
      var j;
      var distanceToNextPoint;
      var bearingToNextPoint;      
      var radius;
      var radiusIncrement;
      var distanceStep = 50;    // Render an intermediate circle every 50km.

      var mapOptions = { 
         mapTypeId: google.maps.MapTypeId.TERRAIN,map: map
         });

         if (i < (pathPoints.length - 1)) {
            distanceToNextPoint = pathPoints[i].distanceTo(pathPoints[i + 1]);
            bearingToNextPoint = pathPoints[i].bearingTo(pathPoints[i + 1]);
            radius = pathPoints[i].radius;
            radiusIncrement = (pathPoints[i + 1].radius - radius) / 
                              (distanceToNextPoint / distanceStep);

            for (j = distanceStep; 
                 j < distanceToNextPoint; 
                 j += distanceStep,radius += radiusIncrement) {

               new google.maps.Circle({
                  center: pathPoints[i].destinationPoint(bearingToNextPoint,map: map
               });
            }
         }
      }

   </script> 
</body> 
</html>

猜你在找的JavaScript相关文章