尝试使用Google Maps API创建“菱形”

时间:2018-11-13 00:57:34

标签: google-maps-api-3 google-polyline

我目前正在使用Google Maps API在地图上绘制点。我正在寻找实现点之间“菱形”效果的最佳方法(参见图片)。 本质上,锭剂的厚度将动态确定。

我看到的唯一方法是在我的点的末端绘制2个圆,并在它们之间创建一个没有边界的矩形。我不喜欢这个主意,因为它实际上是在我的地图上为每条线添加3个多边形,这意味着我必须为每条线(每个多边形上一个)添加3个单击事件以显示所需的数据单击时显示。

有没有更好的方法来实现这一目标?

enter image description here

2 个答案:

答案 0 :(得分:1)

只需创建2条折线...

function initialize() {

  var map = new google.maps.Map(document.getElementById('map-canvas'), {
    zoom: 3,
    center: {lat: 20, lng: 0},
    mapTypeId: 'terrain'
  });

  var flightPlanCoordinates = [
    {lat: 20, lng: -20},
    {lat: 20, lng: 20}
  ];
  
  new google.maps.Polyline({
    path: flightPlanCoordinates,
    geodesic: true,
    strokeColor: '#FF0000',
    strokeOpacity: .3,
    strokeWeight: 20,
    map: map
  });
  
  new google.maps.Polyline({
    path: flightPlanCoordinates,
    geodesic: true,
    strokeColor: '#000000',
    strokeOpacity: 1.0,
    strokeWeight: 1,
    map: map
  });
}

initialize();
#map-canvas {
  height: 200px;
}
<div id="map-canvas"></div>

<script src="https://maps.googleapis.com/maps/api/js"></script>

编辑:

您在评论中提到,您需要将笔触固定在距中心线一定距离的位置。

我仍然可以使用该技术,因为您可以基于纬度和缩放级别来计算地图像素的大小(以米为单位),并且笔触的尺寸也以像素为单位,因此您应该能够在每次放大/缩小时重新计算笔划。由于笔划宽度必须是整数,所以不会100%精确,但是应该可以。

如果在相同的纬度上不同的折线点或多或少都应该起作用,因为具有墨卡托投影的地图分辨率取决于纬度。因此,例如,如果您有一条从-70到+70纬度的大折线,它将不会一直很精确。

这是可用于计算1个地图像素大小的公式。您需要用折线中心点替换map.getCenter().lat()

// Calculate the width of 1 map pixel in meters
let scale = 156543.03392 * Math.cos(map.getCenter().lat() * Math.PI / 180) / Math.pow(2, map.getZoom());

不幸的是,这种方法存在问题。尽管未公开,但折线描边宽度不能大于32px

var map;
var polyBounds;
var polyStroke;
var polyWidth = 50; // Width in meters

function initialize() {

  map = new google.maps.Map(document.getElementById('map-canvas'), {
    zoom: 12,
    center: {
      lat: 20,
      lng: 0
    },
    mapTypeId: 'terrain'
  });

  var flightPlanCoordinates = [{
      lat: 20,
      lng: -0.5
    },
    {
      lat: 20,
      lng: 0.5
    }
  ];

  polyStroke = new google.maps.Polyline({
    path: flightPlanCoordinates,
    geodesic: true,
    strokeColor: '#FF0000',
    strokeOpacity: .3,
    strokeWeight: 0,
    map: map
  });

  new google.maps.Polyline({
    path: flightPlanCoordinates,
    geodesic: true,
    strokeColor: '#000000',
    strokeOpacity: 1.0,
    strokeWeight: 1,
    map: map
  });

  polyBounds = new google.maps.LatLngBounds();

  for (var i = 0; i < flightPlanCoordinates.length; i++) {

    polyBounds.extend(flightPlanCoordinates[i]);
  }

  google.maps.event.addListenerOnce(map, 'idle', setStroke);
  google.maps.event.addListener(map, 'zoom_changed', setStroke);
}

function setStroke() {

  // Calculate the width of 1 map pixel in meters
  let scale = 156543.03392 * Math.cos(polyBounds.getCenter().lat() * Math.PI / 180) / Math.pow(2, map.getZoom());

  polyStroke.setOptions({
    strokeWeight: Math.ceil(polyWidth / scale)
  });
}

initialize();
#map-canvas {
  height: 200px;
}
<div id="map-canvas"></div>

<script src="https://maps.googleapis.com/maps/api/js"></script>

因此,除非您发现这些值适合您的用例,否则这将不是可行的解决方案...

您在评论(How to draw a polygon around a polyline in JavaScript?)中指出的解决方案仍然可能是您的最佳选择。

答案 1 :(得分:0)

我实际上发现了一种使用Google Maps API来实现此目的的简便得多的方法。 内置函数可基于起点获取点的方位角... 因此,我创建了一个函数,该函数接受直线的起点和终点,然后根据标题在这些起点和终点周围创建点-然后使用这些点创建多边形。

var pointCount = 12;
function setLozengePath(startPoint, endPoint) {
  var sp = google.maps.geometry.spherical;
  var heading = sp.computeHeading(startPoint, endPoint);

  var points = [];

  for (var i = 0; i <= pointCount; ++i) {
    points.push(sp.computeOffset(endPoint, radius, heading + 90 - i * 15));
  }

  for (var i = 0; i <= pointCount; ++i) {
    points.push(sp.computeOffset(startPoint, radius, heading - 90 - i * 15));
  }

  return points;
}