【问题标题】:Trying to create a 'lozenge' with google maps API试图用谷歌地图 API 创建一个“菱形”
【发布时间】:2018-11-13 00:57:33
【问题描述】:

我目前正在使用谷歌地图 API 在地图上绘制点。我正在寻找在点之间实现“菱形”效果的最佳方法(见图)。 基本上菱形的厚度是动态确定的。

我能看到的唯一方法是在我的点的末端绘制 2 个圆圈,并在它们之间创建一个没有边框的矩形。我不喜欢这个想法,因为它本质上为我的每条线添加了 3 个多边形,这意味着我必须为每条线添加 3 个点击事件(每个多边形上一个)以显示我想要的数据单击该行时显示。

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

【问题讨论】:

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


【解决方案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>

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

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

【讨论】:

  • 嗨,谢谢。问题在于,当您缩放时,它不会用它来缩放阴影的宽度......我也看过使用 svg,但效果相同。我需要将轮廓限制在距离线 x 米的范围内。
  • 查看我的编辑。这是一个失败,原因很简单...您不能设置大于 32px 的折线笔划宽度 :( 打开功能请求以允许更大的值可能值得...
  • 仅供参考,我创建了这个feature request,你可以订阅它,希望谷歌会改变一些东西......在某个时候。但这可能需要很长时间...... :(
  • 嗨,谢谢你的帮助..我最终所做的只是创建一条折线来显示路径......然后使用起点和终点,然后绞尽脑汁回到高中三角学,我刚刚在直线的每一端创建了一个具有设定半径的弧......这很完美,只是比我想要的要重一些......
  • 酷。随意将您的解决方案作为单独的答案发布,因为它可能对其他人有所帮助!
【解决方案2】:

我实际上发现了一种使用 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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-27
    • 1970-01-01
    • 2012-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-03
    • 2011-03-07
    相关资源
    最近更新 更多