google-maps-api-3 - 折线百分比的纬度

标签 google-maps-api-3

如何沿着折线从给定百分比返回 latLng 值? 我花了一天时间使用插值和单个节点来完成此任务。他们是不是有一个更简单的函数可以让 grunt 工作?

Google map API v3 谢谢!

最佳答案

http://www.geocodezip.com/scripts/v3_epoly.js

为移植到 v3 的 Google Maps Javascript API v2 编写。 Documentation for the v2 version

有这两种方法:

  • .Distance() 返回多边形路径的长度
  • .GetPointAtDistance() 返回指定距离处的 GLatLng
    沿着小路。
    距离以米为单位
    如果路径比该值短则返回 null

这应该有效(如果您包含该脚本并且您的折线变量是“折线”):

var latlng = polyline.GetPointAtDistance(polyline.Distance()*(desired percentage)/100);

当然,如果折线的长度没有变化,那么每次您想在折线上查找点时使用它来计算长度会更有效。

var polylength = polyline.Distance();
var latlng = polylength*(desired percentage)/100);

live example

代码片段:

var directionDisplay;
var directionsService = new google.maps.DirectionsService();
var map;
var polyline = null;
var marker;
var infowindow;

function createMarker(latlng, label, html) {
  // alert("createMarker("+latlng+","+label+","+html+","+color+")");
  var contentString = '<b>' + label + '</b><br>' + html;
  var marker = new google.maps.Marker({
    position: latlng,
    map: map,
    title: label,
    zIndex: Math.round(latlng.lat() * -100000) << 5,
    contentString: contentString
  });
  marker.myname = label;
  // gmarkers.push(marker);

  google.maps.event.addListener(marker, 'click', function() {
    infowindow.setContent(this.contentString);
    infowindow.open(map, marker);
  });
  return marker;
}
var myLatLng = null;
var lat;
var lng;
var zoom = 2;
var maptype;

function initialize() {
  infowindow = new google.maps.InfoWindow();
  myLatLng = new google.maps.LatLng(37.422104808, -122.0838851);
  maptype = google.maps.MapTypeId.ROADMAP;
  // If there are any parameters at eh end of the URL, they will be in  location.search
  // looking something like  "?marker=3"

  // skip the first character, we are not interested in the "?"
  var query = location.search.substring(1);

  // split the rest at each "&" character to give a list of  "argname=value"  pairs
  var pairs = query.split("&");
  for (var i = 0; i < pairs.length; i++) {
    // break each pair at the first "=" to obtain the argname and value
    var pos = pairs[i].indexOf("=");
    var argname = pairs[i].substring(0, pos).toLowerCase();
    var value = pairs[i].substring(pos + 1);

    // process each possible argname  -  use unescape() if theres any chance of spaces
    if (argname == "filename") {
      filename = unescape(value);
    }
    if (argname == "lat") {
      lat = parseFloat(value);
    }
    if (argname == "lng") {
      lng = parseFloat(value);
    }
    if (argname == "start") {
      document.getElementById("start").value = decodeURI(value);
    }
    if (argname == "end") {
      document.getElementById("end").value = decodeURI(value);
    }
    if (argname == "time") {
      document.getElementById("time").value = decodeURI(value);
      // putMarkerOnRoute(parseFloat(document.getElementById('time').value));
    }
    if (argname == "zoom") {
      zoom = parseInt(value);
    }
    if (argname == "type") {
      // from the v3 documentation 8/24/2010
      // HYBRID This map type displays a transparent layer of major streets on satellite images. 
      // ROADMAP This map type displays a normal street map. 
      // SATELLITE This map type displays satellite images. 
      // TERRAIN This map type displays maps with physical features such as terrain and vegetation. 
      if (value == "m") {
        maptype = google.maps.MapTypeId.ROADMAP;
      }
      if (value == "k") {
        maptype = google.maps.MapTypeId.SATELLITE;
      }
      if (value == "h") {
        maptype = google.maps.MapTypeId.HYBRID;
      }
      if (value == "t") {
        maptype = google.maps.MapTypeId.TERRAIN;
      }

    }
  }
  if (!isNaN(lat) && !isNaN(lng)) {
    myLatLng = new google.maps.LatLng(lat, lng);
  }
  var myOptions = {
    zoom: zoom,
    center: myLatLng,
    mapTypeId: maptype
  };
  directionsDisplay = new google.maps.DirectionsRenderer({
    suppressMarkers: true
  });

  map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
  polyline = new google.maps.Polyline({
    path: [],
    strokeColor: '#FF0000',
    strokeWeight: 3
  });
  directionsDisplay.setMap(map);
  calcRoute();
}

function calcRoute() {

  var start = document.getElementById("start").value;
  var end = document.getElementById("end").value;
  var travelMode = google.maps.DirectionsTravelMode.DRIVING

  var request = {
    origin: start,
    destination: end,
    travelMode: travelMode
  };
  directionsService.route(request, function(response, status) {
    if (status == google.maps.DirectionsStatus.OK) {
      polyline.setPath([]);
      var bounds = new google.maps.LatLngBounds();
      startLocation = new Object();
      endLocation = new Object();
      directionsDisplay.setDirections(response);
      var route = response.routes[0];
      var summaryPanel = document.getElementById("directions_panel");
      summaryPanel.innerHTML = "";

      // For each route, display summary information.
      var path = response.routes[0].overview_path;
      var legs = response.routes[0].legs;
      for (i = 0; i < legs.length; i++) {
        if (i == 0) {
          startLocation.latlng = legs[i].start_location;
          startLocation.address = legs[i].start_address;
          // marker = google.maps.Marker({map:map,position: startLocation.latlng});
          // marker = createMarker(legs[i].start_location,"start",legs[i].start_address,"green");
        }
        endLocation.latlng = legs[i].end_location;
        endLocation.address = legs[i].end_address;
        var steps = legs[i].steps;
        for (j = 0; j < steps.length; j++) {
          var nextSegment = steps[j].path;
          for (k = 0; k < nextSegment.length; k++) {
            polyline.getPath().push(nextSegment[k]);
            bounds.extend(nextSegment[k]);
          }
        }
      }

      polyline.setMap(map);

      computeTotalDistance(response);
      putMarkerOnRoute(parseFloat(document.getElementById('percent').value));
    } else {
      alert("directions response " + status);
    }
  });
}

var totalDist = 0;
var totalTime = 0;

function computeTotalDistance(result) {
  totalDist = 0;
  totalTime = 0;
  var myroute = result.routes[0];
  for (i = 0; i < myroute.legs.length; i++) {
    totalDist += myroute.legs[i].distance.value;
    totalTime += myroute.legs[i].duration.value;
  }
  totalDist = totalDist / 1000.
  document.getElementById("total").innerHTML = "total distance is: " + totalDist + " km<br>total time is: " + (totalTime / 60).toFixed(2) + " minutes<br>average speed is: " + (totalDist / (totalTime / 3600)).toFixed(2) + " kph";
  document.getElementById("totalTime").value = (totalTime / 60.).toFixed(2);
}

function putMarkerOnRoute(percent) {
  if (percent > 100) {
    percent = 100;
    document.getElementById('percent').value = percent;
  }

  var distance = percent / 100 * totalDist * 1000;
  // time = ((percentage/100) * totalTIme/60).toFixed(2);
  // alert("Time:"+time+" totalTime:"+totalTime+" totalDist:"+totalDist+" dist:"+distance);
  if (!marker) {
    marker = createMarker(polyline.GetPointAtDistance(distance), "percent: " + percent, "marker");
  } else {
    marker.setPosition(polyline.GetPointAtDistance(distance));
    marker.setTitle("percent:" + percent);
    marker.contentString = "<b>percent: " + percent + "</b><br>distance: " + (distance / 1000).toFixed(2) + " km<br>marker";
    google.maps.event.trigger(marker, "click");
  }
}
google.maps.event.addDomListener(window, 'load', initialize);
// from epoly_v3.js
// modified to use geometry library for length of line segments
// === A method which returns a GLatLng of a point a given distance along the path ===
// === Returns null if the path is shorter than the specified distance ===
google.maps.Polyline.prototype.GetPointAtDistance = function(metres) {
  // some awkward special cases
  if (metres == 0) return this.getPath().getAt(0);
  if (metres < 0) return null;
  if (this.getPath().getLength() < 2) return null;
  var dist = 0;
  var olddist = 0;
  for (var i = 1;
    (i < this.getPath().getLength() && dist < metres); i++) {
    olddist = dist;
    dist += google.maps.geometry.spherical.computeDistanceBetween(this.getPath().getAt(i), this.getPath().getAt(i - 1));
  }
  if (dist < metres) {
    return null;
  }
  var p1 = this.getPath().getAt(i - 2);
  var p2 = this.getPath().getAt(i - 1);
  var m = (metres - olddist) / (dist - olddist);
  return new google.maps.LatLng(p1.lat() + (p2.lat() - p1.lat()) * m, p1.lng() + (p2.lng() - p1.lng()) * m);
}
html {
  height: 100%
}

body {
  height: 100%;
  margin: 0px;
  padding: 0px
}
<!-- Replace the value of the key parameter with your own API key. -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&libraries=geometry"></script>
<div id="tools">
  start:
  <input type="text" name="start" id="start" value="Hyderabad" /> end:
  <input type="text" name="end" id="end" value="Bangalore" />
  <input type="submit" onclick="calcRoute();" /><br /> percentage:
  <input type="text" name="percent" id="percent" value="0" />
  <input type="submit" onclick="putMarkerOnRoute(parseFloat(document.getElementById('percent').value));" /> &nbsp;total time:<input type="text" name="totalTime" id="totalTime" value="0" />
</div>
<div id="map_canvas" style="float:left;width:70%;height:100%;"></div>
<div id="control_panel" style="float:right;width:30%;text-align:left;padding-top:20px">
  <div id="directions_panel" style="margin:20px;background-color:#FFEE77;"></div>
  <div id="total"></div>
</div>

关于google-maps-api-3 - 折线百分比的纬度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19128954/

相关文章:

javascript - 在街景中显示 InfoWindow(使用 InfoBubble)

c# - 使用 C# 中的 Google map API 和 SSIS 包获取行驶距离

javascript - Google Maps : Get click or marker (x, y) 标记点击监听器内的像素坐标

css - Google map 不会在全屏上呈现整个 map

javascript - Angular 谷歌地图正确策略

javascript - 在谷歌地图中添加本地镜像作为自定义标记

android - Jquery 手机 : touch event slower in Android than in iOS

javascript - 回调函数未按预期工作

javascript - Google map 标记的循环问题

javascript - 谷歌热图根据强度改变颜色