Показывать маркеры (из базы данных) на маршруте Google Directions

У меня есть карта Google, которая отображает станции технического обслуживания в континентальной Европе и может рассчитывать маршруты между двумя точками. Однако из-за большого количества станций карта может показаться довольно загруженной. Поэтому я хочу отображать только маркеры, которые следуют по маршруту, указанному мной в Google.

Я думал об отслеживании направлений с помощью ломаной линии и, возможно, с использованием перехвата, но я не могу придумать, как разговаривать с базой данных. В моем текущем примере направления показаны красной ломаной линией, но показаны все маркеры.

Код для javascript:

//<![CDATA[

var customIcons = {
  as24: {
    icon: 'images/as24.png'
  },
  pearson: {
    icon: 'images/p.png'
  }
};

var rendererOptions = {
draggable: true
};
var directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions);
var directionsService = new google.maps.DirectionsService();
var map, trafficLayer;
var europe = new google.maps.LatLng(-25.274398, 133.775136);

function initialize() {

var mapOptions = {
zoom: 6,
center: europe
};

map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);

directionsDisplay.setMap(map);
directionsDisplay.setPanel(document.getElementById('directionsPanel'));

google.maps.event.addListener(directionsDisplay, 'directions_changed', function() {
computeTotalDistance(directionsDisplay.getDirections());
});

trafficLayer = new google.maps.TrafficLayer();
    trafficLayer.setMap(map);

    var control = document.getElementById('traffic-wpr');
    map.controls[google.maps.ControlPosition.TOP_RIGHT].push(control);

    google.maps.event.addDomListener(control, 'click', function() {
      trafficLayer.setMap(trafficLayer.getMap() ? null : map);
    });

 calcRoute();
 }



function calcRoute() {
var start = document.getElementById('start').value;
var end = document.getElementById('end').value;
var request = {
  origin:start,
  destination:end,
  //waypoints:[{location: 'London, England'}, {location: 'Paris, France'}],
  travelMode: google.maps.TravelMode.DRIVING
 };
 directionsService.route(request, function(response, status) {
 if (status == google.maps.DirectionsStatus.OK) {
  directionsDisplay.setDirections(response);
 }
var polyline = new google.maps.Polyline({
 path: [],
 strokeColor: "#FF0000",
        strokeOpacity: 0.2,
        strokeWeight: 30,
        fillColor: "#FF0000",
        fillOpacity: 0.35
});
var bounds = new google.maps.LatLngBounds();


var legs = response.routes[0].legs;
for (i=0;i<legs.length;i++) {
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);
map.fitBounds(bounds);

 });
}



function computeTotalDistance(result) {
var total = 0;
var myroute = result.routes[0];
for (var i = 0; i < myroute.legs.length; i++) {
total += myroute.legs[i].distance.value;
}
total = total / 1000.0;
document.getElementById('total').innerHTML = total + ' km';
}
google.maps.event.addDomListener(window, 'load', initialize);


function load() {

  var infoWindow = new google.maps.InfoWindow;

  // Change this depending on the name of your PHP file
  downloadUrl("as24_genxml.php", function(data) {
    var xml = data.responseXML;
    var markers = xml.documentElement.getElementsByTagName("marker");
    for (var i = 0; i < markers.length; i++) {
      var name = markers[i].getAttribute("name");
      var address = markers[i].getAttribute("address");
      var price = markers[i].getAttribute("price");
      var type = markers[i].getAttribute("type");
      var point = new google.maps.LatLng(
          parseFloat(markers[i].getAttribute("lat")),
          parseFloat(markers[i].getAttribute("lng")));
      var html = "<b>" + name + " " + price + "</b> <br/>" + address;
      var icon = customIcons[type] || {}; 
      var marker = new google.maps.Marker({
        map: map,
        position: point,
        icon: icon.icon
      });
      map.getBounds().contains(marker.getPosition())
      bindInfoWindow(marker, map, infoWindow, html);
    }
  });
}

function bindInfoWindow(marker, map, infoWindow, html) {
  google.maps.event.addListener(marker, 'click', function() {
    infoWindow.setContent(html);
    infoWindow.open(map, marker);
  });
}

function downloadUrl(url, callback) {
  var request = window.ActiveXObject ?
      new ActiveXObject('Microsoft.XMLHTTP') :
      new XMLHttpRequest;

  request.onreadystatechange = function() {
    if (request.readyState == 4) {
      request.onreadystatechange = doNothing;
      callback(request, request.status);
    }
  };

  request.open('GET', url, true);
  request.send(null);
}




function doNothing() {}

//]]>

Код маркеров (as24_genxml.php):

<?php include ('php/config.php');

function parseToXML($htmlStr) 
{ 
$xmlStr=str_replace('<','&lt;',$htmlStr); 
$xmlStr=str_replace('>','&gt;',$xmlStr); 
$xmlStr=str_replace('"','&quot;',$xmlStr); 
$xmlStr=str_replace("'",'&#39;',$xmlStr); 
$xmlStr=str_replace("&",'&amp;',$xmlStr); 
return $xmlStr; 
} 

// Opens a connection to a MySQL server
$connection=mysql_connect (localhost, $mysql_user, $mysql_pass);
if (!$connection) {
die('Not connected : ' . mysql_error());
}

// Set the active MySQL database
$db_selected = mysql_select_db($mysql_db, $connection);
if (!$db_selected) {
  die ('Can\'t use db : ' . mysql_error());
}

// Select all the rows in the markers table
$query = "SELECT * FROM as24 WHERE 1";
$result = mysql_query($query);
if (!$result) {
  die('Invalid query: ' . mysql_error());
}

header("Content-type: text/xml");

// Start XML file, echo parent node
echo '<markers>';

// Iterate through the rows, printing XML nodes for each
while ($row = @mysql_fetch_assoc($result)){
  // ADD TO XML DOCUMENT NODE
  echo '<marker ';
  echo 'name="' . parseToXML($row['name']) . '" ';
  echo 'address="' . parseToXML($row['address']) . '" ';
  echo 'price="' . parseToXML($row['price']) . '" ';
  echo 'lat="' . $row['lat'] . '" ';
  echo 'lng="' . $row['lng'] . '" ';
  echo 'type="' . $row['type'] . '" ';
  echo '/>';
}

// End XML file
echo '</markers>';

?>

Кажется, я не могу найти никого, у кого была бы подобная проблема. Я могу слишком усложнять ситуацию, используя ломаную линию?


person tomantford    schedule 23.01.2014    source источник
comment
Служба маршрутов предоставляет вам объект Route, содержащий все путевые точки. developers.google.com/maps/documentation/javascript/directions Затем вы необходимо определить Вдоль маршрута и, возможно, показать маркеры, которые находятся в определенном диапазоне вокруг ваших путевых точек. Для этого вы можете проверить мой ответ здесь: stackoverflow.com/a/21043061/1238965   -  person MrUpsidown    schedule 23.01.2014
comment
Никогда бы не подумал об этом вопросе, хорошо сыграно. Раньше я всегда запрашивал элементы МЕЖДУ координатами из объекта границ карты, а затем сужал их по радиусу во внешнем интерфейсе.   -  person ChrisSwires    schedule 23.01.2014
comment
Что ж, это может быть нормальное решение, а может и нет. Например, что произойдет, если вы выберете все маркеры в пределах 10 км и эти 2 путевые точки разделены 50 км? Это нужно будет проверить.   -  person MrUpsidown    schedule 23.01.2014
comment
Спасибо за комментарии @MrUpsidown и Swires. Это может лучше показать дилемму: thoford.co.uk/pp/stations_map .php? from = eindhoven & to = berlin   -  person tomantford    schedule 23.01.2014
comment
Как мы переключаем маркеры?   -  person MrUpsidown    schedule 23.01.2014
comment
@MRUpsidown Нет возможности переключать маркеры, вместо этого каждый раз, когда вызывается calcRoute (), я хочу, чтобы отображались маркеры, которые находятся в границах направлений / многоугольника.   -  person tomantford    schedule 23.01.2014
comment
Ну что ж, вы сказали в своем вопросе, что карта выглядит загруженной, поэтому я подумал, что увижу это ... Теперь, в чем вы хотите, чтобы мы вам помогли? Вы проверили объект Route, как было предложено?   -  person MrUpsidown    schedule 23.01.2014
comment
Да, я посмотрел на раздел weypoints, но, похоже, это работает таким образом, что направления меняются. Я не хочу, чтобы маршрут проходил через конкретную путевую точку, я просто хочу, чтобы маркеры отображались только в том случае, если они появляются вдоль маршрута.   -  person tomantford    schedule 23.01.2014
comment
позвольте нам продолжить обсуждение в чате   -  person tomantford    schedule 23.01.2014
comment
@Geocodezip - оцените ссылку на ваш ответ. Именно тот человек, которого я искал! Ваш ответ почти то, что мне нужно, но я хочу загружать события из mysql ..?   -  person tomantford    schedule 23.01.2014
comment
Ага. Замените запросы мест запросами к вашей базе данных.   -  person geocodezip    schedule 23.01.2014
comment
Конечно, но не в краткосрочной перспективе, у меня нет вашей базы данных, и у меня сейчас мало времени. Есть и другие вопросы по SO о том, как запрашивать в базах данные маркеры внутри границ.   -  person geocodezip    schedule 23.01.2014


Ответы (1)


Хорошо, я не уверен, что я слишком усложняю это, если честно, но если вы просто хотите, чтобы карта выглядела менее загроможденной, вам не нужно ничего менять в серверной части (при условии, что у вас нет проблемы с производительностью, я не уверен, о каком количестве точек мы здесь говорим. Все, что вам нужно сделать, это проверить расстояние между каждой координатой на ломаной линии и каждым маркером «станции обслуживания».

Пример того, как этого добиться, доступен в первой части ответа здесь. Вы даже можете скрыть ломаную линию, чтобы еще больше уменьшить беспорядок, или удалить ее и использовать координаты в каждом сегменте пути для достижения того же эффекта.

Однако это может быть проблемой, если у вас есть много точек для проверки и длинные маршруты. Единственный способ узнать наверняка - это попробовать, но асимптотическая сложность невелика.

person ChrisSwires    schedule 23.01.2014