【问题标题】:Selecting section of polyline - Google Maps Api选择折线的部分 - Google Maps Api
【发布时间】:2016-05-19 03:49:51
【问题描述】:

是否可以在 Google 地图中仅选择折线的一部分?我有用户添加的标记,并且在标记之间绘制了一条折线。两个标记之间的折线代表两个地方之间的路线。我希望用户能够单击折线,该部分会改变颜色,然后插入另一个点。我还想获取折线连接的标记的标记 ID(在添加标记时设置)。

这是我的代码所基于的谷歌示例代码,因为我的代码非常混乱,所以我将其发布。

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<title>Complex Polylines</title>
<style>
    html, body
    {
        height: 100%;
        margin: 0;
        padding: 0;
    }
    #map
    {
        height: 100%;
    }
</style>
</head>
<body>
<div id="map">
</div>
   <script>
       var poly;
       var map;

    function initMap() {
        map = new google.maps.Map(document.getElementById('map'), {
            zoom: 7,
            center: { lat: 41.879, lng: -87.624}  // Center the map on Chicago, USA.
        });

        poly = new google.maps.Polyline({
            strokeColor: '#000000',
            strokeOpacity: 1.0,
            strokeWeight: 3
        });
        poly.setMap(map);

        // Add a listener for the click event
        map.addListener('click', addLatLng);
    }

    // Handles click events on a map, and adds a new point to the Polyline.
    function addLatLng(event) {
        var path = poly.getPath();

        // Because path is an MVCArray, we can simply append a new coordinate
        // and it will automatically appear.
        path.push(event.latLng);

        // Add a new marker at the new plotted point on the polyline.
        var marker = new google.maps.Marker({
            position: event.latLng,
            title: '#' + path.getLength(),
            map: map
        });
    }

 </script>
 <script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&signed_in=true&callback=initMap"></script>
</body>
</html>

到目前为止,我只设法为整个折线添加了一个点击事件侦听器:

 google.maps.event.addListener(poly, 'click', function() {
   poly.setOptions({strokeColor: '#76EE00'});
 });

【问题讨论】:

  • 我认为SO-6170176 可能会有所帮助。
  • @gerardnimo 谢谢,我确实看过那个问题,但我仍然不知道如何将它应用于我的问题。

标签: javascript jquery google-maps google-maps-api-3


【解决方案1】:

为了获得最接近的折线,我使用三角形依赖关系,因此对于每对标记,我计算点之间的距离 (d^ = (x2-x1)^ + (y2-y1)^),接下来从 Heron's formula 获取三角形面积,而不是从 p=(a*h)/2 得到三角形的高度,这是我们的点到折线的距离。 我还通过距离来划分高距离以关闭标记点以获得最近的部分 - 它并不完美,但效果很好。

当我们得到我们的部分时,必须恢复完整路径,更改标记顺序并完成。

因此,当您单击折线时,它应该会突出显示,如果再次单击,则会出现新的标记并移除突出显示,并且主路径可以从最后一个标记继续。

这里正在工作JSFiddle

var poly, map, 
markers = {}, // here we handle all markers
tmp_path = null, // temporary path for select sections
id_i = 1, // initial value for marker id
MD = []; // selection section markers id

function initMap() {
  map = new google.maps.Map(document.getElementById('map'), {
    zoom: 7,
    center: { lat: 41.879, lng: -87.624}  // Center the map on Chicago, USA.
  });

  poly = new google.maps.Polyline({
    strokeColor: '#000000',
    strokeOpacity: 1.0,
    strokeWeight: 3
  });
  poly.setMap(map);

  // Add a listener for the click event
  map.addListener('click', addLatLng);
  poly.addListener('click', polyOnClick);

}



function polyOnClick(event) {
    if(tmp_path !== null) tmp_path.setMap(null);
    tmp_path = null;

    var
    p_x = event.latLng.lat(),
    p_y = event.latLng.lng(),
    min_dist = 999999;


    $.each(markers, function(k, v) {
      if(typeof markers[(v.id+1)] == 'undefined') return false;

      var 
      m_x = v.x,
      m_y = v.y,
      m2_x = markers[(v.id+1)].x,
      m2_y = markers[(v.id+1)].y;


      var
      a = getDist(m_x, m2_x, m_y, m2_y), 
            b = getDist(m_x, p_x, m_y, p_y),
      c = getDist(p_x, m2_x, p_y, m2_y);
      var h = getHgh(a, b, c);

      var min_mark_dist = (c > b)? b : c;

      console.info(h/min_mark_dist);

      if((h/min_mark_dist) < min_dist) {
        min_dist = (h/min_mark_dist);
        MD = [v.id, markers[(v.id+1)].id];
      }

    });


    // append temporary path to haighlight section
    tmp_path = new google.maps.Polyline({
      path: [{lat: markers[MD[0]].x, lng: markers[MD[0]].y},{lat: markers[MD[1]].x, lng: markers[MD[1]].y}],
      geodesic: true,
      strokeColor: '#76EE00',
      strokeOpacity: 1,
      strokeWeight: 6
    });

    tmp_path.addListener('click', tmp_pathOnClick);
    tmp_path.setMap(map);
}

function tmp_pathOnClick(event) {
    tmp_path.setMap(null);
    tmp_path = null;

    /* restore markers order and path */
   var tmp_markers = {}, 
   ctx_marker_id = 0; // here we handle pushed marker id
   var full_path = [], flag = false;
   id_i = 1; 

    $.each(markers, function(k, v) {
      if(MD[0] < v.id && !flag) {
        flag = true;
        full_path.push(event.latLng);
        ctx_marker_id = id_i;
        tmp_markers[id_i] = {id: id_i, x: event.latLng.lat(), y: event.latLng.lng()};
        id_i++;
      }

      full_path.push({lat: v.x, lng: v.y});
      tmp_markers[id_i] = {id: id_i, x: v.x, y: v.y, marker: v.marker};
      v.marker.setTitle('#'+id_i);
      id_i++;
    });

    markers = tmp_markers;

    // create new marker
    var marker = new google.maps.Marker({
      position: event.latLng,
      title: '#' + ctx_marker_id,
      map: map,
      id: ctx_marker_id
    });

    markers[ctx_marker_id].marker = marker;


    /* restore main path */
    poly.setMap(null); // clear view
    poly = null; // delete object

    poly = new google.maps.Polyline({
      strokeColor: '#000000',
      strokeOpacity: 1.0,
      strokeWeight: 3,
      path: full_path
    });
    poly.setMap(map); 

    poly.addListener('click', polyOnClick);
    MD = []; // clear selected section markers id
}

// get distance between two points
function getDist(x1, x2, y1, y2) {
    return Math.sqrt(Math.pow((x2 - x1), 2) + Math.pow((y2 - y1), 2));
}

// get hight from abc triangle 
function getHgh(a, b, c) {
    var p = (a+b+c)/2;
  var F = Math.sqrt((p * (p-a) * (p-b) * (p-c)), 2);
  return 2*F/a; 
}



// Handles click events on a map, and adds a new point to the Polyline.
function addLatLng(event) {
    console.log('addLatLng');

  if(MD.length) return false;
  if(tmp_path !== null) tmp_path.setMap(null);
  tmp_path = null;

  var path = poly.getPath();

  // Because path is an MVCArray, we can simply append a new coordinate
  // and it will automatically appear.
  path.push(event.latLng);


  // Add a new marker at the new plotted point on the polyline.
  var marker = new google.maps.Marker({
    position:  event.latLng,
    title: '#' + path.getLength(),
    map: map,
    id: id_i
  });

  markers[id_i++] = {id: marker.id, x: marker.position.lat(), y: marker.position.lng(), marker: marker};
}

【讨论】:

  • 完美!!这正是我一直在寻找的。你的方法很有趣!谢谢你的回答:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-02
  • 2014-08-15
  • 2014-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多