断言失败:无效:setMap:不是 Map 的实例
Assertion failed: Invalid: setMap: not an instance of Map
我是 JS 的新手并且 google api。去年我开发了一个自定义 google 地图。基本上它从 xml 加载多边形建筑轮廓,然后为特定的兴趣点应用 kml 图层。(非常感谢 geocodezip 为我指明了正确的方向)
这是一个用于加载停止工作的 kml 图层功能的工作测试版。 devbox
但现在有人要求我有一个搜索框,我用搜索框重建了它,但现在加载 kml 层不起作用,我看到错误 Assertion failed: InvalidValueError: setMap: not an instance的地图。
<!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>
您的 map
变量是 initMap 函数的局部变量(注意它前面的 var
)。要在 HTML 单击事件侦听器(如复选框的侦听器)中使用它,它需要在全局范围内。改变这个:
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 48.490802, lng: -123.416497},
zoom: 17
});
收件人:
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 48.490802, lng: -123.416497},
zoom: 17
});
我是 JS 的新手并且 google api。去年我开发了一个自定义 google 地图。基本上它从 xml 加载多边形建筑轮廓,然后为特定的兴趣点应用 kml 图层。(非常感谢 geocodezip 为我指明了正确的方向) 这是一个用于加载停止工作的 kml 图层功能的工作测试版。 devbox
但现在有人要求我有一个搜索框,我用搜索框重建了它,但现在加载 kml 层不起作用,我看到错误 Assertion failed: InvalidValueError: setMap: not an instance的地图。
<!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>
您的 map
变量是 initMap 函数的局部变量(注意它前面的 var
)。要在 HTML 单击事件侦听器(如复选框的侦听器)中使用它,它需要在全局范围内。改变这个:
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 48.490802, lng: -123.416497},
zoom: 17
});
收件人:
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 48.490802, lng: -123.416497},
zoom: 17
});