【问题标题】:google directions: how to get transit_details?谷歌路线:如何获取公交详细信息?
【发布时间】:2023-03-19 16:31:02
【问题描述】:

编辑:这个问题得到解决,感谢 geocodezip 的帮助,他在 cmets 中为我指出了正确的方式......

问题: 我想要来自谷歌的公交路线作为纯文本,我需要transit_details。我尝试添加所有变体,例如(不起作用):

steps[i].transit.arrival_stop.name

解决方案:大多数公交路线都有步行的第一步和最后一步。在这种情况下,.transit 不存在并产生错误。

我相应地修复了下面的代码(现在可以使用)。

<!DOCTYPE html>
<html>

<head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
  <title></title>
  <script type="text/javascript" src="http://maps.google.com/maps/api/js?"></script>
</head>

<body style="font-family: Arial; font-size: 12px; color:#FFFFFF;" bgcolor="#202020">
  <div id="panel" style="width: 300px; float: left;"></div>
  <div id="map" style="width: 300px; height: 300px;"></div>
  <script type="text/javascript">

  calcRoute();

  function calcRoute() {
    var directionsService = new google.maps.DirectionsService();
    var directionsDisplay = new google.maps.DirectionsRenderer();

    var map = new google.maps.Map(document.getElementById('map'), {
      zoom: 7,
      mapTypeId: google.maps.MapTypeId.ROADMAP,
    });

    directionsDisplay.setMap(map);

    var request = {
      origin: 'Potsdamer Platz, 10785 Berlin',
      destination: 'Falckensteinstraße, Berlin',
      travelMode: google.maps.DirectionsTravelMode.TRANSIT,
    };

    directionsService.route(request, function(response, status) {
      if (status == google.maps.DirectionsStatus.OK) {
        directionsDisplay.setDirections(response);
        writeDirectionsSteps(directionsDisplay.directions.routes[0].legs[0].steps);
      }
      else {
        console.error('DirectionsStatus is ' + status);
      }
    });
  }

  function writeDirectionsSteps(steps) {
    var directions = document.getElementById('panel');
    directions.innerHTML = '';
    for (var i = 0; i < steps.length; i++) {
      directions.innerHTML += '<br/><br/>' + steps[i].instructions + '<br/>' + steps[i].distance.text;
      if (typeof steps[i].transit !== "undefined") {
        directions.innerHTML += '<br/>' + steps[i].transit.arrival_stop.name;
      }
    }
  }

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

(代码基于:Google Maps Api v3: How to change the Default waypoint markers in the Directions (set)Panel?

非常感谢任何帮助!

【问题讨论】:

  • 如果我查看Google Maps Javascript API v3 DirectionsStep object 的文档,它有一个名为transit 的属性,即Google Maps Javascript API v3 TransitDetails object。我在 steps 数组中看到了一个属性 transit。您在解析时遇到什么问题?
  • 感谢您的回复!我得到“TypeError:steps[i].transit is undefined”——不管我尝试使用steps[i].transit.arrival_stop.name还是steps[i].transit_details.arrival_stop.name...
  • 请张贴minimal reproducible example,说明您的问题中的问题。并非所有步骤都有.transit 属性(第一个和最后一个往往是“行走”,那些不会有那个属性。)
  • 嗨更新了我的帖子以显示完整(非)工作代码,见上文 - 错误部分在第 49 行。另外,关于步骤是否具有传输属性 - 以防万一,难道不应该只提供任何内容(或未定义)而不是停止整个脚本......?我需要如何调整我的脚本来处理这个问题?再次感谢您的帮助!
  • 更新:感谢您的帮助,我解决了!我添加了一个循环检查typeof steps[i].transit !== "undefined",就可以了。现在,因为我是这个论坛的新手:我如何接受您的评论作为答案(如果是评论)?

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


【解决方案1】:

您需要进行防御性编码。 .transit 属性不会出现在所有步骤中,只有那些涉及实际交通本身的步骤(即不在往返车站的步行中)。

function writeDirectionsSteps(steps) {
  var directions = document.getElementById('panel');
  directions.innerHTML = '';
  for (var i = 0; i < steps.length; i++) {
    directions.innerHTML += '<br/><br/>' + steps[i].instructions + '<br/>' + steps[i].distance.text;
    // if .transit property exists
    if (!!steps[i].transit) {
      directions.innerHTML += '<br/>' + steps[i].transit.arrival_stop.name;
    }
  }
}

proof of concept fiddle

代码 sn-p:

var directionsDisplay;
var directionsService = new google.maps.DirectionsService();
var map;
var routeBounds = false;
var overlayWidth = 200; // Width of the overlay DIV
var leftMargin = 30; // Grace margin to avoid too close fits on the edge of the overlay
var rightMargin = 80; // Grace margin to avoid too close fits on the right and leave space for the controls

overlayWidth += leftMargin;

var start = new google.maps.LatLng(3.148173, 101.7148792);
var end = new google.maps.LatLng(3.1347725, 101.6893408);

function initialize() {

  var btn1 = document.getElementById('calcRoute');
  btn1.addEventListener('click', calcRoute);

  var btn2 = document.getElementById('offsetMap');
  btn2.addEventListener('click', offsetMap);

  var btn3 = document.getElementById('fitAndOffsetMap');
  btn3.addEventListener('click', fitAndOffsetMap);

  var btn4 = document.getElementById('fitMap');
  btn4.addEventListener('click', fitMap);

  directionsDisplay = new google.maps.DirectionsRenderer({
    draggable: true
  });

  var mapOptions = {
    zoom: 13,
    mapTypeId: google.maps.MapTypeId.ROADMAP,
    center: start,
    panControlOptions: {
      position: google.maps.ControlPosition.TOP_RIGHT
    },
    zoomControlOptions: {
      position: google.maps.ControlPosition.TOP_RIGHT
    }
  };

  map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
  directionsDisplay.setMap(map);
}

function offsetMap() {

  if (routeBounds !== false) {

    // Clear listener defined in directions results
    google.maps.event.clearListeners(map, 'idle');

    // Top right corner
    var topRightCorner = new google.maps.LatLng(map.getBounds().getNorthEast().lat(), map.getBounds().getNorthEast().lng());

    // Top right point
    var topRightPoint = fromLatLngToPoint(topRightCorner).x;

    // Get pixel position of leftmost and rightmost points
    var leftCoords = routeBounds.getSouthWest();
    var leftMost = fromLatLngToPoint(leftCoords).x;
    var rightMost = fromLatLngToPoint(routeBounds.getNorthEast()).x;

    // Calculate left and right offsets
    var leftOffset = (overlayWidth - leftMost);
    var rightOffset = ((topRightPoint - rightMargin) - rightMost);

    // Only if left offset is needed
    if (leftOffset >= 0) {

      if (leftOffset < rightOffset) {

        var mapOffset = Math.round((rightOffset - leftOffset) / 2);

        // Pan the map by the offset calculated on the x axis
        map.panBy(-mapOffset, 0);

        // Get the new left point after pan
        var newLeftPoint = fromLatLngToPoint(leftCoords).x;

        if (newLeftPoint <= overlayWidth) {

          // Leftmost point is still under the overlay
          // Offset map again
          offsetMap();
        }

      } else {

        // Cannot offset map at this zoom level otherwise both leftmost and rightmost points will not fit
        // Zoom out and offset map again
        map.setZoom(map.getZoom() - 1);
        offsetMap();
      }
    }
  }
}

function fromLatLngToPoint(latLng) {

  var scale = Math.pow(2, map.getZoom());
  var nw = new google.maps.LatLng(map.getBounds().getNorthEast().lat(), map.getBounds().getSouthWest().lng());
  var worldCoordinateNW = map.getProjection().fromLatLngToPoint(nw);
  var worldCoordinate = map.getProjection().fromLatLngToPoint(latLng);

  return new google.maps.Point(Math.floor((worldCoordinate.x - worldCoordinateNW.x) * scale), Math.floor((worldCoordinate.y - worldCoordinateNW.y) * scale));
}

function calcRoute() {

  var request = {
    origin: start,
    destination: end,
    travelMode: google.maps.DirectionsTravelMode.TRANSIT,
    transitOptions: {
      departureTime: new Date("01/03/2017 9:00 AM EST")
    }

  };

  directionsService.route(request, function(response, status) {

    if (status == google.maps.DirectionsStatus.OK) {

      directionsDisplay.setDirections(response);

      // Define route bounds for use in offsetMap function
      routeBounds = response.routes[0].bounds;

      // Write directions steps
      writeDirectionsSteps(response.routes[0].legs[0].steps);

      // Wait for map to be idle before calling offsetMap function
      google.maps.event.addListener(map, 'idle', function() {

        // Offset map
        offsetMap();
      });

      // Listen for directions changes to update bounds and reapply offset
      google.maps.event.addListener(directionsDisplay, 'directions_changed', function() {

        // Get the updated route directions response
        var updatedResponse = directionsDisplay.getDirections();

        // Update route bounds
        routeBounds = updatedResponse.routes[0].bounds;

        // Fit updated bounds
        map.fitBounds(routeBounds);

        // Write directions steps
        writeDirectionsSteps(updatedResponse.routes[0].legs[0].steps);

        // Offset map
        offsetMap();
      });
    }
  });
}

function writeDirectionsSteps(steps) {
  var directions = document.getElementById('overlayContent');
  directions.innerHTML = '';
  for (var i = 0; i < steps.length; i++) {
    directions.innerHTML += '<br/><br/>' + steps[i].instructions + '<br/>' + steps[i].distance.text;
    // if .transit property exists
    if (!!steps[i].transit) {
      directions.innerHTML += '<br/>station name:' + steps[i].transit.arrival_stop.name;
    }
  }
}

function fitMap() {

  if (routeBounds !== false) {

    map.fitBounds(routeBounds);
  }
}

function fitAndOffsetMap() {

  if (routeBounds !== false) {

    map.fitBounds(routeBounds);
    offsetMap();
  }
}

initialize();
body {
  margin: 0;
  padding: 0;
  font-family: Arial;
}
#map-canvas {
  height: 450px;
}
#overlay {
  position: absolute;
  width: 200px;
  height: 450px;
  background: black;
  opacity: .8;
  top: 0;
  left: 0;
  overflow: auto;
}
#overlayContent {
  color: white;
  padding: 10px 20px;
}
#overlayContent p {
  font-size: 12px;
  margin: 6px 0;
}
#overlayContent small {
  display: block;
  text-align: right;
  font-style: italic;
}
small {
  font-size: 9px;
}
i {
  color: lightblue;
}
h1 {
  font-size: 20px;
}
h5 {
  font-size: 12px;
}
button {
  margin: 20px 0 0 20px;
}
<script src="https://maps.googleapis.com/maps/api/js?libraries=geometry"></script>
<div id="map-canvas"></div>
<div id="overlay">
  <div id="overlayContent">
    <h1>DIV OVERLAY</h1>

    <h5>Routes should not be drawn below this element.</h5>

    <h5>Click the <i>Calc route</i> button to draw the directions route.</h5>

    <h5><i>Map offset</i> will be applied automatically.</h5>

    <h5><i>Drag the route</i> to see how it is applied.</h5>

    <h5>Click the <i>Offset map</i> button to reapply the offset.</h5>

    <h5>Click the <i>Fit only</i> button to only fit route bounds.</h5>

    <h5>Click the <i>Fit and offset map</i> button to fit to route bounds and reapply offset.</h5>

  </div>
</div>
<button id="calcRoute">Calc route</button>
<button id="offsetMap">Offset map</button>
<button id="fitMap">Fit only</button>
<button id="fitAndOffsetMap">Fit and offset map</button>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-26
    • 1970-01-01
    • 1970-01-01
    • 2021-04-09
    • 1970-01-01
    • 2011-03-24
    • 2013-05-20
    • 1970-01-01
    相关资源
    最近更新 更多