javascript - 如何将文本文件处理为 Google map 航点 + 信息文本

标签 javascript php google-maps google-maps-api-3 geolocation

我想使用 Google map 使用文本文件中的位置数据和时间戳来显示路线。
文本文件 (route.log) 包含由 Unix 换行符分隔的行,并遵循以下格式:“Lat,Long;date, time”。
示例:

52.1615470947258,20.805144309997561;14.03.2015, 17:33 52.15991486090931,20.804049968719483;14.03.2015, 17:37 52.15772967999426,20.805788040161133;14.03.2015, 17:47

第一行是起点,最后一行是终点,每行之间都是一个路点。每行末尾的时间戳(日期、时间)应在每个航路点的信息文本中显示。

现在我找到了一个使用 Google map 显示航路点的非常好的示例 here .

我的问题是:

如何将文本文件中的行处理为与 that Google Maps example 兼容的格式(数组) ? 如何为每个标记信息文本添加时间戳?

如果我的文本文件只有 2 个点(开始 + 结束)或者可能有 1 个点,它会抛出错误还是存在“故障安全”?

我将非常感谢您的帮助和提示。非常感谢。

<小时/> <小时/>

我一直在尝试使用 AJAX/jQuery,下面是示例中我现在陷入困境的部分代码:

    <script>
  jQuery(function() {
    $.ajax({
url: "route.log",
dataType: 'text',
success: function (data) {
    var lines = data.match(/^.*((\r\n|\n|\r)|$)/gm);
    var stops = [];
    for (var i = 0; i < lines.length; i++) {
        var line = lines[i].replace("\n", "").split(";");
        stops.push(line);
    }
    //console.log(stops[0][1]);
}
});

var map = new window.google.maps.Map(document.getElementById("map"));
var directionsDisplay = new window.google.maps.DirectionsRenderer({suppressMarkers: true});
var directionsService = new window.google.maps.DirectionsService();

Tour_startUp(stops); // this here gets executed before the AJAX part has delivered the stops array > error

window.tour.loadMap(map, directionsDisplay);
window.tour.fitBounds(map);

if (stops.length > 1)
    window.tour.calcRoute(directionsService, directionsDisplay);       
});
function Tour_startUp(stops) {... // etc.

似乎在 AJAX 完成填充 Stops 数组之前执行了一些需要 AJAX 结果(stops 数组)的代码。

此外,在引用的 example code 中停靠点数组如下所示:

var stops = [
{"Geometry":{"Latitude":52.1615470947258,"Longitude":20.80514430999756}},
{"Geometry":{"Latitude":52.15991486090931,"Longitude":20.804049968719482}},
{"Geometry":{"Latitude":52.15772967999426,"Longitude":20.805788040161133}}]

如果 javascript 可以将文本文件行转换为这个格式添加时间戳作为第三部分,我可以使用示例代码的其余部分,而无需进一步修改它很多。另外,我需要删除文本文件末尾的空行(因为它添加了一个空数组元素)。

<小时/> <小时/>

编辑2:

这是完整的代码,包括。最新变化:

<!doctype html>
    <?php
$fileContent = file('route.log', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
     foreach($fileContent as $line_num => $line) {
     { 
       $data = explode(";", rtrim($line));
       $geometry[] = explode(",", trim($data[0]));
       $timestamp[] = trim($data[1]);
     }
     }; 
    ?>

<html>
  <head>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
    <meta charset="utf-8">
    <title>Google Maps JavaScript API v3 Example: Directions Waypoints</title>
<style>
    #map{
    width: 100%;
    height: 450px;
}
</style>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
    <script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
    <script>

     jQuery(function() {
        var stops = <?php
                echo '[ ';  
                foreach ($geometry as $row) {
                    echo '{"Geometry":{"Latitude":' . $row['0'] . ','. '"Longitude":' . $row['1'] . '}},' . "\n";
                }
                echo ' ]';              
        ?>;

    var map = new window.google.maps.Map(document.getElementById("map"));

    // new up complex objects before passing them around
    var directionsDisplay = new window.google.maps.DirectionsRenderer({suppressMarkers: true});
    var directionsService = new window.google.maps.DirectionsService();

    Tour_startUp(stops);

    window.tour.loadMap(map, directionsDisplay);
    window.tour.fitBounds(map);

    if (stops.length > 1)
        window.tour.calcRoute(directionsService, directionsDisplay);
});

function Tour_startUp(stops) {
    var stops_timestamp = JSON.parse( '<?php echo json_encode($timestamp) ?>' );

    if (!window.tour) window.tour = {
        updateStops: function (newStops) {
            stops = newStops;
        },
        // map: google map object
        // directionsDisplay: google directionsDisplay object (comes in empty)
        loadMap: function (map, directionsDisplay) {
            var myOptions = {
                zoom: 13,
                center: new window.google.maps.LatLng(51.507937, -0.076188), // default to London
                mapTypeId: window.google.maps.MapTypeId.ROADMAP
            };
            map.setOptions(myOptions);
            directionsDisplay.setMap(map);
        },
        fitBounds: function (map) {
            var bounds = new window.google.maps.LatLngBounds();

            // extend bounds for each record
            jQuery.each(stops, function (key, val) {
                var myLatlng = new window.google.maps.LatLng(val.Geometry.Latitude, val.Geometry.Longitude);
                bounds.extend(myLatlng);
            });
            map.fitBounds(bounds);
        },
        calcRoute: function (directionsService, directionsDisplay) {
            var batches = [];
            var itemsPerBatch = 10; // google API max = 10 - 1 start, 1 stop, and 8 waypoints
            var itemsCounter = 0;
            var wayptsExist = stops.length > 0;

            while (wayptsExist) {
                var subBatch = [];
                var subitemsCounter = 0;

                for (var j = itemsCounter; j < stops.length; j++) {
                    subitemsCounter++;
                    subBatch.push({
                        location: new window.google.maps.LatLng(stops[j].Geometry.Latitude, stops[j].Geometry.Longitude),
                        stopover: true
                    });
                    if (subitemsCounter == itemsPerBatch)
                        break;
                }

                itemsCounter += subitemsCounter;
                batches.push(subBatch);
                wayptsExist = itemsCounter < stops.length;
                // If it runs again there are still points. Minus 1 before continuing to
                // start up with end of previous tour leg
                itemsCounter--;
            }

            // now we should have a 2 dimensional array with a list of a list of waypoints
            var combinedResults;
            var unsortedResults = [{}]; // to hold the counter and the results themselves as they come back, to later sort
            var directionsResultsReturned = 0;

            for (var k = 0; k < batches.length; k++) {
                var lastIndex = batches[k].length - 1;
                var start = batches[k][0].location;
                var end = batches[k][lastIndex].location;

                // trim first and last entry from array
                var waypts = [];
                waypts = batches[k];
                waypts.splice(0, 1);
                waypts.splice(waypts.length - 1, 1);

                var request = {
                    origin: start,
                    destination: end,
                    waypoints: waypts,
                    travelMode: window.google.maps.TravelMode.WALKING
                };
                (function (kk) {
                    directionsService.route(request, function (result, status) {

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

                            var unsortedResult = { order: kk, result: result };
                            unsortedResults.push(unsortedResult);

                            directionsResultsReturned++;

                            if (directionsResultsReturned == batches.length) // we've received all the results. put to map
                            {
                                // sort the returned values into their correct order
                                unsortedResults.sort(function (a, b) { return parseFloat(a.order) - parseFloat(b.order); });
                                var count = 0;
                                for (var key in unsortedResults) {
                                    if (unsortedResults[key].result != null) {
                                        if (unsortedResults.hasOwnProperty(key)) {
                                            if (count == 0) // first results. new up the combinedResults object
                                                combinedResults = unsortedResults[key].result;
                                            else {
                                                // only building up legs, overview_path, and bounds in my consolidated object. This is not a complete
                                                // directionResults object, but enough to draw a path on the map, which is all I need
                                                combinedResults.routes[0].legs = combinedResults.routes[0].legs.concat(unsortedResults[key].result.routes[0].legs);
                                                combinedResults.routes[0].overview_path = combinedResults.routes[0].overview_path.concat(unsortedResults[key].result.routes[0].overview_path);

                                                combinedResults.routes[0].bounds = combinedResults.routes[0].bounds.extend(unsortedResults[key].result.routes[0].bounds.getNorthEast());
                                                combinedResults.routes[0].bounds = combinedResults.routes[0].bounds.extend(unsortedResults[key].result.routes[0].bounds.getSouthWest());
                                            }
                                            count++;
                                        }
                                    }
                                }
                                directionsDisplay.setDirections(combinedResults);
                                var legs = combinedResults.routes[0].legs;
                                // alert(legs.length);
                                for (var i=0; i < legs.length;i++){
                  var markerletter = "A".charCodeAt(0);
                  markerletter += i;
                                  markerletter = String.fromCharCode(markerletter);
                                  createMarker(directionsDisplay.getMap(),legs[i].start_location,"Marker "+i,stops_timestamp[i]+"<br>"+legs[i].start_address,markerletter);
                                }
                                var i=legs.length;
                                var markerletter = "A".charCodeAt(0);
                    markerletter += i;
                                markerletter = String.fromCharCode(markerletter);
                                createMarker(directionsDisplay.getMap(),legs[legs.length-1].end_location,"Most Recent Position: Marker "+i,stops_timestamp[i]+"<br>"+legs[legs.length-1].end_address,markerletter);
                            }
                        }

                        //troubleshooting part follows
                        /*

                        else {
                                  // alert an error message when the route could nog be calculated.
                                  if (status == 'ZERO_RESULTS') {
                                    alert('No route could be found between the origin and destination.');
                                  } else if (status == 'UNKNOWN_ERROR') {
                                    alert('A directions request could not be processed due to a server error. The request may succeed if you try again.');
                                  } else if (status == 'REQUEST_DENIED') {
                                    alert('This webpage is not allowed to use the directions service.');
                                  } else if (status == 'OVER_QUERY_LIMIT') {
                                    alert('The webpage has gone over the requests limit in too short a period of time.');
                                  } else if (status == 'NOT_FOUND') {
                                    alert('At least one of the origin, destination, or waypoints could not be geocoded.');
                                  } else if (status == 'INVALID_REQUEST') {
                                    alert('The DirectionsRequest provided was invalid.');        
                                  } else {
                                    alert("There was an unknown error in your request. Requeststatus: nn"+status);
                                  }
                             }                 
                        //*/
                    });
                })(k);
            }
        }
    };
}
var infowindow = new google.maps.InfoWindow(
  { 
    size: new google.maps.Size(150,50)
  });

var icons = new Array();
icons["red"] = new google.maps.MarkerImage("mapIcons/marker_red.png",
      // This marker is 20 pixels wide by 34 pixels tall.
      new google.maps.Size(20, 34),
      // The origin for this image is 0,0.
      new google.maps.Point(0,0),
      // The anchor for this image is at 9,34.
      new google.maps.Point(9, 34));



function getMarkerImage(iconStr) {
   if ((typeof(iconStr)=="undefined") || (iconStr==null)) { 
      iconStr = "red"; 
   }
   if (!icons[iconStr]) {
      icons[iconStr] = new google.maps.MarkerImage("http://www.google.com/mapfiles/marker"+ iconStr +".png",
      // This marker is 20 pixels wide by 34 pixels tall.
      new google.maps.Size(20, 34),
      // The origin for this image is 0,0.
      new google.maps.Point(0,0),
      // The anchor for this image is at 6,20.
      new google.maps.Point(9, 34));
   } 
   return icons[iconStr];

}
  // Marker sizes are expressed as a Size of X,Y
  // where the origin of the image (0,0) is located
  // in the top left of the image.

  // Origins, anchor positions and coordinates of the marker
  // increase in the X direction to the right and in
  // the Y direction down.

  var iconImage = new google.maps.MarkerImage('mapIcons/marker_red.png',
      // This marker is 20 pixels wide by 34 pixels tall.
      new google.maps.Size(20, 34),
      // The origin for this image is 0,0.
      new google.maps.Point(0,0),
      // The anchor for this image is at 9,34.
      new google.maps.Point(9, 34));
  var iconShadow = new google.maps.MarkerImage('http://www.google.com/mapfiles/shadow50.png',
      // The shadow image is larger in the horizontal dimension
      // while the position and offset are the same as for the main image.
      new google.maps.Size(37, 34),
      new google.maps.Point(0,0),
      new google.maps.Point(9, 34));
      // Shapes define the clickable region of the icon.
      // The type defines an HTML &lt;area&gt; element 'poly' which
      // traces out a polygon as a series of X,Y points. The final
      // coordinate closes the poly by connecting to the first
      // coordinate.
  var iconShape = {
      coord: [9,0,6,1,4,2,2,4,0,8,0,12,1,14,2,16,5,19,7,23,8,26,9,30,9,34,11,34,11,30,12,26,13,24,14,21,16,18,18,16,20,12,20,8,18,4,16,2,15,1,13,0],
      type: 'poly'
  };


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

    google.maps.event.addListener(marker, 'click', function() {
        infowindow.setContent(contentString); 
        infowindow.open(map,marker);
        });
    return marker;
}
    </script>
  </head>
  <body>
  <div id="map"></div>
</body>
</html>

现在有点可以工作了。正如你所看到的,我使用 php 将文本行转换为正确的格式并放入 stops Javascript 数组中(+将文件扩展名更改为 index.php)。

唯一剩下的问题是,有时 GoogleMaps JSON 返回未知错误并且不会绘制路线。它与某些地理编码位置有关。有些地理坐标有效,有些则无效。 您可以自己检查,只需在文本文件名 route.log 中添加一些坐标并进行测试即可。

最佳答案

我将在这里回答您问题的第一部分,即如何处理文本文件中的行

您将需要通过 AJAX 请求打开文本文件。我强烈建议您使用jQuery为此。

$.ajax({
    url: "route.log",
    dataType: 'text',
    success: function (data) {

        var lines = data.match(/^.*((\r\n|\n|\r)|$)/gm);

        for (var i = 0; i < lines.length; i++) {

            var line = lines[i].replace("\n", "").split(";");
            console.log(line);
        }
    }
});

这将输出:

["52.1615470947258,20.805144309997561", "14.03.2015, 17:33"] ["52.15991486090931,20.804049968719483", "14.03.2015, 17:37"] ["52.15772967999426,20.805788040161133", "14.03.2015, 17:47"]

所以基本上,line[0] 将是您的经纬度坐标,line[1] 将是您的日期/时间信息。

这样您就可以轻松处理不同的线路(起点和终点、航路点),并检查是否有足够的线路来请求路线。

希望这有帮助。

编辑:

关于数据的格式,您可以这样做:

var stops = [];

$.ajax({
    url: "test.txt",
    dataType: 'text',
    success: function(data) {

        var lines = data.match(/^.*((\r\n|\n|\r)|$)/gm);

        for (var i = 0; i < lines.length; i++) {

            var line = lines[i].replace("\n", "").split(";");
            var geometry = line[0].split(",");

            stops.push({
                "Geometry": {
                    "Latitude": geometry[0],
                    "Longitude": geometry[1]
                },
                "Timestamp": line[1]
            });
        }

        console.log(stops);
    }
});

关于javascript - 如何将文本文件处理为 Google map 航点 + 信息文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29062708/

相关文章:

PHP 正则表达式 : Problem with Smiley `:)` and `:))`

jquery - 将变量从 Google map 传递到 jQuery

javascript - 将 Jquery/html 变量链接到 javascript

javascript - 将数组元素从一个数组位置移动到另一个位置

javascript - 基于对象映射检查数组中的任何值是否为 false 的最有效方法

javascript - 按国家名称排序

javascript - 放大/缩小时保持 map 上 D3 对象大小不变

php - 两个表逗号的mysql结果集

javascript - 谷歌地图 API v3 : Earliest EVENT to inform me of the bounds?

Android 谷歌地图 ListView 与 onClickListener()