Javascript TypeError

时间:2013-10-01 19:34:47

标签: javascript jquery google-app-engine google-maps

从数据库中选择记录并在地图上设置动画。我在firebug控制台中遇到 TypeError ,我找不到导致错误的原因。没有绘制标记并且没有动画发生。 makeRouteCallback 函数出现错误。

使用console.log()显示rNum具有正确的值0,1,2,3,4。

错误

TypeError: polyline[rNum] is undefined
polyline[rNum].setMap(map);

我还在 makeRouteCallback 函数中为'status'做了一个console.log,它打印了NOT_FOUND而不是OK

代码

<%@ include file="/WEB-INF/jsp/include.jsp" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

<%@ taglib prefix = "fmt" uri= "http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix = "c" uri= "http://java.sun.com/jsp/jstl/core" %>

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />

    <link href="<c:url value="/resources/css/crimeTrackMap.css" />" rel="stylesheet" type="text/css" media="screen" />        
    <script type="text/javascript"  src="http://maps.googleapis.com/maps/api/js?key=AIzaSyAuJC5ega61cLlvCB14uKxoheUmh61Wwmc&sensor=true"></script>      
    <script src="/crimeTrack/resources/js/markermanager.js"></script>   

    <script src="/crimeTrack/resources/js/v3_epoly.js"></script>    

    <script src="/crimeTrack/resources/js/jquery-1.9.1.js"></script>

    <script src="http://code.jquery.com/jquery-1.9.0.js"></script>
    <script src="http://code.jquery.com/jquery-migrate-1.0.0.js"></script>

    <script type="text/javascript">

    var map;
    var directionDisplay;
    var directionsService;
    var stepDisplay;

    var position;
    var marker        = [];
    var polyline      = [];
    var poly          = [];
    var poly2         = [];
    var startLocation = [];
    var endLocation   = [];
    var timerHandle   = [];    

    var speed = 0.000005, wait = 1;
    var infowindow = null;

    var myPano;   
    var panoClient;
    var nextPanoId;

    var global_citizens = new Array();


    var Colors = ["#FF0000", "#00FF00", "#0000FF"];

    //------------------------------------------------------------

    function GetCitizensForTracking(){

        $.ajax({
            type: 'GET',
            async : false,
            global: 'false',
            url: 'getListOfMarkers.htm',
            headers : {Accept: 'application/json'},
            dataType: 'json'
        }).done(function(citizens) {
            global_citizens = citizens;

            $.each(citizens, function(i, c) {
            //console.log(c.name + ' | ' + c.socialSecurityNumber + ' | ' + c.lat+ ' | ' +c.lng);
            //citizen.push(c.name);
            console.log(global_citizens[i].name+','+global_citizens[i].citizenType);

            });             
        });     
    }      


    //---------------------------------------------------------------------

  function initialize() {  

    infowindow = new google.maps.InfoWindow(
      { 
        size: new google.maps.Size(150,50)
      });

      var myOptions = {
        zoom: 11,
        mapTypeId: google.maps.MapTypeId.ROADMAP
      }
      map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);

      address = 'Trinidad and Tobago'
      geocoder = new google.maps.Geocoder();
      geocoder.geocode( { 'address': address}, function(results, status) {
      map.fitBounds(results[0].geometry.viewport);

    });


    } 

    //------------------------------------------------------------------------------

  function createMarker(latlng, label, html,citizenType) {

     var contentString = '<b>'+label+'</b><br>'+html;

     //console.log('Citizen icon is '+citizenType);     

    //replaces if...then..else...else if. Icon source are placed in an array that corresponds to value of the citizenType.
    //array starts from 0 . The first value of the citizens type is 2 so array should have a value at the 2 location 
    //so jquery will map the icon to the citizenType based on its matching location in the array

      var markerSource = [null,
                          null,
                         'resources/icons/criminal_new.ico',
                         'resources/icons/victim_new.ico',
                         'resources/icons/suspect_new.ico'];

      var icon = markerSource[citizenType];


        var marker = new google.maps.Marker({
           position: latlng,
           map: map,
           title: label,
           icon: new google.maps.MarkerImage(icon),
           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;
  }  

  //---------------------------------------------------------------------------------

  function setRoutes(){ 

    var directionsDisplay = new Array();

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

    var rendererOptions = {
        map: map,
        suppressMarkers : true,
         preserveViewport: true
    }
    directionsService = new google.maps.DirectionsService();

    var travelMode = google.maps.DirectionsTravelMode.DRIVING;  


    var request = {
        origin: global_citizens[i].startLat+','+global_citizens[i].startLng,
        destination: global_citizens[i].endLat+','+global_citizens[i].endLng,
        travelMode: travelMode
    };  

        directionsService.route(request,makeRouteCallback(i,directionsDisplay[i],global_citizens[i].citizenType));
        console.log("Set Routes "+global_citizens[i].name +' - '+global_citizens[i].citizenType);

    }   

  //------------------------------------------------------------------------------------

    function makeRouteCallback(rNum, disp,ctype){   
     if (polyline[rNum] && (polyline[rNum].getMap() != null)) {
           startAnimation(rNum);
           return;
          }

        return function(response, status){      

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

            var bounds = new google.maps.LatLngBounds();
            var route = response.routes[0];
            startLocation[rNum] = new Object();
            endLocation[rNum] = new Object();


            polyline[rNum] = new google.maps.Polyline({
            path: [],
            strokeColor: '#FFFF00',
            strokeWeight: 3
            });

            poly2[rNum] = new google.maps.Polyline({
            path: [],
            strokeColor: '#FFFF00',
            strokeWeight: 3
            });     


            // For each route, display summary information.
            var path = response.routes[0].overview_path;
            var legs = response.routes[0].legs;

            disp = new google.maps.DirectionsRenderer(rendererOptions);     
            disp.setMap(map);
            disp.setDirections(response);


            //Markers               
            for (i=0;i<legs.length;i++) {
              if (i == 0) { 
                startLocation[rNum].latlng = legs[i].start_location;
                startLocation[rNum].address = legs[i].start_address;
                // marker = google.maps.Marker({map:map,position: startLocation.latlng});               

                //console.log('(i) The Citizen Type Is : '+ global_citizens[i].citizenType);

                marker[rNum] = createMarker(legs[i].start_location,"start",legs[i].start_address,ctype);                    

              }

              endLocation[rNum].latlng = legs[i].end_location;
              endLocation[rNum].address = legs[i].end_address;
              var steps = legs[i].steps;

              for (j=0;j<steps.length;j++) {
                var nextSegment = steps[j].path;                
                var nextSegment = steps[j].path;

                for (k=0;k<nextSegment.length;k++) {
                    polyline[rNum].getPath().push(nextSegment[k]);
                    //bounds.extend(nextSegment[k]);            


                }

              }
            }           
        }


         polyline[rNum].setMap(map);
         //map.fitBounds(bounds);        
        startAnimation(rNum);   

        }

    }  

  }
    var lastVertex = 1;
    var stepnum=0;
    var step = 90; //0.9 metres
    var tick = 100; // milliseconds
    var eol = [];
  //----------------------------------------------------------------------              
   function updatePoly(i,d) {
   // Spawn a new poly line every 20 vertices, because updating a 100-vertex poly is too slow
    if (poly2[i].getPath().getLength() > 20) {
            poly2[i]=new google.maps.Polyline([polyline[i].getPath().getAt(lastVertex-1)]);
            // map.addOverlay(poly2)
          }

      if (polyline[i].GetIndexAtDistance(d) < lastVertex+2) {
          if (poly2[i].getPath().getLength()>1) {
              poly2[i].getPath().removeAt(poly2[i].getPath().getLength()-1)
          }
            poly2[i].getPath().insertAt(poly2[i].getPath().getLength(),polyline[i].GetPointAtDistance(d));
      } else {
          poly2[i].getPath().insertAt(poly2[i].getPath().getLength(),endLocation[i].latlng);
      }     

   }
  //----------------------------------------------------------------------------

  function animate(index,d) {

     if (d>eol[index]) {

        marker[index].setPosition(endLocation[index].latlng);
        return;
     }
      var p = polyline[index].GetPointAtDistance(d);

      //map.panTo(p);
      marker[index].setPosition(p);
      updatePoly(index,d);
      timerHandle[index] = setTimeout("animate("+index+","+(d+step)+")", tick);




    if(marker[0].getPosition() == endLocation[0].latlng){
        console.log('Completed');
    //alert("Marker One Complete"); 
    }
  }

  //-------------------------------------------------------------------------

  function startAnimation(index) {
        if (timerHandle[index]) clearTimeout(timerHandle[index]);
          eol[index]=polyline[index].Distance();
          map.setCenter(polyline[index].getPath().getAt(0));

          poly2[index] = new google.maps.Polyline({path: [polyline[index].getPath().getAt(0)], strokeColor:"#FFFF00", strokeWeight:3});

          timerHandle[index] = setTimeout("animate("+index+",50)",2000);  // Allow time for the initial map display         

  }

  //----------------------------------------------------------------------------      

 $(document).ready(function(){   


    $('#getCitizens').on('click', function() {

        if(global_citizens == undefined || global_citizens.length == 0 ){
            GetCitizensForTracking();    
            setRoutes();        
        }else{alert("Tracking In Progress");}

    });     


}); 


</script>





  </head>
  <body onload="initialize()">
    <div id="map_canvas" style="width:100%; height:90%">

    <!-- MAP GOES IN HERE -->

    </div>

    <div id="toolbar">
        <button class="btn" id="getCitizens" onclick="" type="button">Get Citizens</button>
        <button class="btn" id="startTracking" onclick="" type="button">Start Tracking</button>
        <button class="btn" id="pauseTracking" onclick="" type="button">Pause Tracking</button>

    </div>
  </body>
</html>

2 个答案:

答案 0 :(得分:1)

触发错误的行:

polyline[rNum].setMap(map);

...未置于填充polyline

的条件下
if (status == google.maps.DirectionsStatus.OK){
  //code
}

当条件失败时,失败的语句仍然会被执行....带有错误。

将回调的最后2个语句移动到status - 条件。

答案 1 :(得分:0)

您可以尝试将折线变量声明为字典,如下所示:

polyline = {}