Assertion failed: Invalid: setMap: not an instance

2019-09-02 02:02发布

I am Novice at JS and google api. I've developing a custom google map off and on this last year. Basically it loads polygon building outlines from xml, then applies kml layers for certain point of interest.(big thanks to geocodezip for point me in the right direction) Here is a working beta for loading kml layer function that stopped working. devbox

But now I have been requested for it have a search box, I rebuilt it with a searchbox, but now the loading kml layer doesn't work and I see the error Assertion failed: InvalidValueError: setMap: not an instance of map.

    <!DOCTYPE html>
<html>
  <head>
    <title>Place Autocomplete</title>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
    <meta charset="utf-8">
    <link rel="stylesheet" type="text/css" href="../maps.css">
    <style>
    html, body {
        height: 100%;
        margin: 0;
        padding: 0;
      } 
      #map {
        height: 100%;
        width: 800px;
        float: right;
       margin: 0;
        padding: 0;
        /* height: 840px; */
       width: 939px; 
      /*height: 700px;
     width: 700px;*/
       position: relative;
        overflow: hidden;
        transform: translateZ(0px);
        background-color: rgb(229, 227, 223);
    border: 1px solid #8a8c8f 
      }
.controls {
  margin-top: 10px;
  border: 1px solid transparent;
  border-radius: 2px 0 0 2px;
  box-sizing: border-box;
  -moz-box-sizing: border-box;
  height: 32px;
  outline: none;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
}

#pac-input {
  background-color: #fff;
  font-family: Roboto;
  font-size: 15px;
  font-weight: 300;
  margin-left: 12px;
  padding: 0 11px 0 13px;
  text-overflow: ellipsis;
  width: 300px;
}

#pac-input:focus {
  border-color: #4d90fe;
}

.pac-container {
  font-family: Roboto;
}

#type-selector {
  color: #fff;
  background-color: #4d90fe;
  padding: 5px 11px 0px 11px;
}

#type-selector label {
  font-family: Roboto;
  font-size: 13px;
  font-weight: 300;
}
.instructions {
    height: 100%;
}
.top {
    width: 100%;    
}

    </style>
<script type="text/javascript" src="https://maps.google.com/maps/api/js?sensor=false"></script>
       <script type="text/javascript" src="geoxml3.js"></script>
<script type="text/javascript" src="ProjectedOverlay.js"></script> 

  </head>
  <body>
  <!-- Header Container -->
  <div class="top">
    <div class="header">
        <div class="headerLogo">
            <a href="http://camosun.ca"></a>
        </div>
        <div class="headerTitle">
            <a href="/maps/"></a>
        </div>

    </div>
  </div>
<!-- header div -->
  <section class="instructions">
<h1>Interurban Campus</h1>
<p>Test to create a custom Interurban campus map.</p>
<aside class="functions">
 <!-- begin - MAP LAYERS CHECKBOXES -->
<h3>Points of Interest</h3>
<form action="" method="post">
<input name="checkbox" alt="Parking checkbox"  onClick="boxclick(this,4)" type="checkbox" value="checkbox" > Parking<br>
<input name="checkbox" alt="Parking checkbox"  onClick="boxclick(this,5)" type="checkbox" value="checkbox" > Foodservices<br>
<input name="checkbox" alt="Parking checkbox"  onClick="boxclick(this,6)" type="checkbox" value="checkbox" > Bookstore<br>
<input name="checkbox" alt="Emergency Phones checkbox"  onClick="boxclick(this,3)" type="checkbox" value="checkbox" > Bike Racks<br>
<input name="checkbox" alt="Road Closure checkbox"  onClick="boxclick(this,8)" type="checkbox" value="checkbox" > ATM<br>
<input name="checkbox" alt="Construction checkbox"  onClick="boxclick(this,7)" type="checkbox" value="checkbox" > Coffee<br>
<input name="checkbox" alt="Bike Routes checkbox" onClick="boxclick(this,1)" type="checkbox" value="checkbox" > Bike Routes<br>
<input name="checkbox" alt="Traffic checkbox" onClick="boxclick(this,2)" type="checkbox" value="checkbox"> Traffic<br>
<input name="checkbox" alt="Library checkbox" onClick="boxclick(this,9)" type="checkbox" value="checkbox"> Library</p>
</form>    
<!-- end - MAP LAYERS CHECKBOXES -->   


<!-- begin - Unordered list of locations --> 
<h3>Locations</h3>              
<div id="sidebar"></div>

</aside>
</section>
<script type="text/javascript">

/* *** begin - KML LAYERS *** */
// Random number generated for cache-busting
var seconds = new Date().getTime();
// Google Bike & Traffic Layers
var bikeLayer = new google.maps.BicyclingLayer();
var trafficLayer = new google.maps.TrafficLayer();
// Variables set to URLs of custom KML layers made in Google Earth  
var bikeRacksLayer = new google.maps.KmlLayer('https://webservices.camosun.bc.ca/maps-demo/_data/bike-racks-iu.kml');   
var parkingLayer = new google.maps.KmlLayer('https://webservices.camosun.bc.ca/maps-demo/_data/parking-iu.kml');            
var foodservicesLayer = new google.maps.KmlLayer('https://webservices.camosun.bc.ca/maps-demo/_data/foodservices-iu.kml');  
var bookstoreLayer = new google.maps.KmlLayer('https://webservices.camosun.bc.ca/maps-demo/_data/bookstore-iu.kml');    
var coffeeLayer = new google.maps.KmlLayer('https://webservices.camosun.bc.ca/maps-demo/_data/coffee-iu.kml');  
var atmLayer = new google.maps.KmlLayer('https://webservices.camosun.bc.ca/maps-demo/_data/atm-iu.kml');    
var libraryLayer = new google.maps.KmlLayer('https://webservices.camosun.bc.ca/maps-demo/_data/library-iu.kml');    
// Switch loop to toggle layers on and off  
function boxclick(box,num) { 
    switch (num)
        {
            case 1:
                if (box.checked)
                    {bikeLayer.setMap(map.getMap());} 
                else {bikeLayer.setMap(null);}
                break;
            case 2:
                if (box.checked)
                    {trafficLayer.setMap(map);} 
                else {trafficLayer.setMap(null);} 
                break;  
            case 3:
                if (box.checked)
                    {bikeRacksLayer.setMap(map);} 
                else {bikeRacksLayer.setMap(null);}
                break; 
            case 4:
                if (box.checked)
                    {parkingLayer.setMap(map)} 
                else {parkingLayer.setMap(null);}
                break;
            case 5:
                if (box.checked)
                    {foodservicesLayer.setMap(map);} 
                else {foodservicesLayer.setMap(null);}
                break;   
            case 6:
                if (box.checked)
                    {bookstoreLayer.setMap(map);} 
                else {bookstoreLayer.setMap(null);}
                break; 
            case 7:
                if (box.checked)
                    {coffeeLayer.setMap(map);} 
                else {coffeeLayer.setMap(null);}
                break;   
            case 8:
                if (box.checked)
                    {atmLayer.setMap(map);} 
                else {atmLayer.setMap(null);}
                break;      
            case 9:
                if (box.checked)
                    {libraryLayer.setMap(map);} 
                else {libraryLayer.setMap(null)}
                break;   
            } //Switch 

    } // funtion
    /* *** end - KML Layers *** */

</script>


    <input id="pac-input" class="controls" type="text"
        placeholder="Enter a location">
    <div id="type-selector" class="controls">
      <input type="radio" name="type" id="changetype-all" checked="checked">
      <label for="changetype-all">All</label>

      <input type="radio" name="type" id="changetype-establishment">
      <label for="changetype-establishment">Establishments</label>

      <input type="radio" name="type" id="changetype-address">
      <label for="changetype-address">Addresses</label>

      <input type="radio" name="type" id="changetype-geocode">
      <label for="changetype-geocode">Geocodes</label>
    </div>
    <div id="map"></div>

    <script>
function initMap() {
  var map = new google.maps.Map(document.getElementById('map'), {
    center: {lat: 48.490802, lng: -123.416497},
    zoom: 17
  });

    // array of styles
    var styles = [
        {
            "featureType": "poi.school",
            "elementType": "labels",
            "stylers": [{ "visibility": "off" }]
        },{
            "featureType": "poi.business",
            "elementType": "labels",
            "stylers": [{ "visibility": "off" }]
        },{
            "featureType": "landscape.man_made",
            "elementType": "labels.text",
            "stylers": [{ "visibility": "off" }]
        },{
            "featureType": "landscape.man_made",
            "elementType": "geometry",
            "stylers": [{ "visibility": "off" }]
        }];
// new styledMapType object, passing the array of styles and the name to be displayed on the map type control.
    var styledMap = new google.maps.StyledMapType(styles,{name: "Styled Map"});
    map.mapTypes.set('map_style', styledMap);
    map.setMapTypeId('map_style');

    // Sets geoxml class options
   geoXml = new geoXML3.parser({
            map: map,
            singleInfoWindow: true,
            afterParse: useTheData
                });
   geoXml.parse('interurb.xml');

        // sets the min and max zoom levels of the map
    var opt = { minZoom: 6, maxZoom: 18 };
    map.setOptions(opt);

  var input = /** @type {!HTMLInputElement} */(
      document.getElementById('pac-input'));

  var types = document.getElementById('type-selector');
  map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);
  map.controls[google.maps.ControlPosition.TOP_LEFT].push(types);

  var autocomplete = new google.maps.places.Autocomplete(input);
  autocomplete.bindTo('bounds', map);

  var infowindow = new google.maps.InfoWindow();
  var marker = new google.maps.Marker({
    map: map,
    anchorPoint: new google.maps.Point(0, -29)
  });

  autocomplete.addListener('place_changed', function() {
    infowindow.close();
    marker.setVisible(false);
    var place = autocomplete.getPlace();
    if (!place.geometry) {
      window.alert("Autocomplete's returned place contains no geometry");
      return;
    }

    // If the place has a geometry, then present it on a map.
    if (place.geometry.viewport) {
      map.fitBounds(place.geometry.viewport);
    } else {
      map.setCenter(place.geometry.location);
      map.setZoom(17);  // Why 17? Because it looks good.
    }
    marker.setIcon(/** @type {google.maps.Icon} */({
      url: place.icon,
      size: new google.maps.Size(71, 71),
      origin: new google.maps.Point(0, 0),
      anchor: new google.maps.Point(17, 34),
      scaledSize: new google.maps.Size(35, 35)
    }));
    marker.setPosition(place.geometry.location);
    marker.setVisible(true);

    var address = '';
    if (place.address_components) {
      address = [
        (place.address_components[0] && place.address_components[0].short_name || ''),
        (place.address_components[1] && place.address_components[1].short_name || ''),
        (place.address_components[2] && place.address_components[2].short_name || '')
      ].join(' ');
    }

    infowindow.setContent('<div><strong>' + place.name + '</strong><br>' + address);
    infowindow.open(map, marker);



  });

  // Sets a listener on a radio button to change the filter type on Places
  // Autocomplete.
  function setupClickListener(id, types) {
    var radioButton = document.getElementById(id);
    radioButton.addEventListener('click', function() {
      autocomplete.setTypes(types);
    });
  }

  setupClickListener('changetype-all', []);
  setupClickListener('changetype-address', ['address']);
  setupClickListener('changetype-establishment', ['establishment']);
  setupClickListener('changetype-geocode', ['geocode']);
}
function kmlClick(marker) {
   google.maps.event.trigger(geoXml.docs[0].markers[marker],"click");
}

function useTheData(doc){
  // Geodata handling goes here, using JSON properties of the doc object
  // Creates side bar navigation
  var sidebarHtml = "<table>";
  for (var i = 0; i < doc[0].markers.length; i++) {
    // console.log(doc[0].markers[i].title);
    sidebarHtml += '<tr><td><a href="javascript:kmlClick('+i+');">'+doc[0].placemarks[i].name+'</a></td></tr>';
  }
  sidebarHtml += "</table>";
  document.getElementById("sidebar").innerHTML = sidebarHtml;
};

    </script>
    <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyASPL99-mPNhM87jKpOPoALZOUFMHCx1Ag&signed_in=true&libraries=places&callback=initMap"
        async defer></script>

  </body>
</html>

1条回答
做个烂人
2楼-- · 2019-09-02 02:39

Your map variable is local to the initMap function (notice the var in front of it). To use it in HTML click event listeners (like those for the checkboxes), it needs to be in the global scope. Change this:

function initMap() {
  var map = new google.maps.Map(document.getElementById('map'), {
    center: {lat: 48.490802, lng: -123.416497},
    zoom: 17
  });

To:

var map;
function initMap() {
  map = new google.maps.Map(document.getElementById('map'), {
    center: {lat: 48.490802, lng: -123.416497},
    zoom: 17
  });

proof of concept fiddle

查看更多
登录 后发表回答