我正在使用Google Maps API构建地图,当我加载它时,我收到此错误:
未捕获的TypeError:无法读取属性' setMap'未定义的
我认为来自vm()的toggle()导致错误,但我不知道如何纠正错误。 我的目标是同时根据搜索显示标记。
以下是代码:
var locations = [
{"name": "Marari Beach Alappuzha" ,'location': {'lat': 9.618406, 'lng': 76.340161} },
{"name": "Tea Mueseum" ,'location': {'lat': 10.049198, 'lng': 77.051025 }},
{"name": "Eravikulam National Park" ,'location': {'lat': 10.116233, 'lng': 77.067791} },
{"name": "Chimmini Wildlife Sanctuary" ,'location': {'lat': 10.428646, 'lng': 76.491031} },
{"name": "Bekal Fort ",'location': {'lat': 12.440895, 'lng': 75.030311 }}
]
var markers = [];
var map;
var boolean = [];
for(i=0;i<locations.length;i++){
boolean[i] = true;
}
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 7,
center: {
lat: 10.850516,
lng: 76.271080
}
});
var labels = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
for (var i = 0; i < locations.length; i++) {
var position = locations[i].location;
var name = locations[i].name;
var marker = new google.maps.Marker({
// map:map,
position: position,
animation: google.maps.Animation.DROP,
id: i
});
markers.push(marker);
marker.addListener('click', (function(marker, i) {
return function() {
if (marker.getAnimation() != null) {
marker.setAnimation(null);
} else {
marker.setAnimation(google.maps.Animation.BOUNCE);
stopAnimation(marker);
}
}
})(marker, i));
function stopAnimation(marker) {
setTimeout(function() {
marker.setAnimation(null);
}, 3000);
};
}
toggle();
}
function toggle(){
for(g=0;g<locations.length;g++){
if(boolean[g] === true){
markers[g].setMap(map);
}else if(boolean[g] === false){
markers[g].setMap(null);
}
}
}
var z,g;
var vm = function(){
var self = this;
self.loc = ko.observableArray(locations);
self.query = ko.observable('');
self.filteredloc = ko.computed(function () {
z=0;
var filter = self.query().toLowerCase();
console.log(boolean);
toggle();
if (!filter) {
return self.loc();
} else {
return ko.utils.arrayFilter(self.loc(), function (item) {
boolean[z] = item.name.toLowerCase().indexOf(filter) !== -1;
// console.log(boolean[z]+'in pos'+z);
z++;
return item.name.toLowerCase().indexOf(filter) !== -1;
});
}
});
};
ko.applyBindings(new vm());
&#13;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compaitable" content="IE-edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Neighbourhood Map</title>
<link rel="stylesheet" href="style.css">
<script src="http://ajax.microsoft.com/ajax/jquery/jquery-1.4.2.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script defer src="mapping.js"></script>
<script asyc defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAZJYwSB-hwX7EXVNXtWo7HSjyPaJNmrWc&callback=initMap"></script>
</head>
<body>
<div class="container">
<div class="row">
<div id="content" class="col-3">
<div id="content_search">
<form action="#">
<input placeholder="Search…" type="search" name="q" data-bind="value: query, valueUpdate: 'keyup'" autocomplete="off">
</form>
</div>
<div class="content_data">
<ul id="content_data--style" data-bind="template: {name:'location', foreach:filteredloc}"></ul>
</div>
</div>
<div class="col-9">
<h3 >Neighbourhood Map</h3>
<div id="map"></div>
</div>
</div>
</div>
<script type="text/html" id="location">
<li>
<strong data-bind="text: name"></strong>
</li>
</script>
</body>
</html>
&#13;
答案 0 :(得分:0)
我没有适合您的解决方案,但我想向您展示一些可以大大简化JavaScript代码的方法。
首先,我摆脱了单独的<em lang="en"></em>
和markers
数组。相反,最好制作boolean
数组元素的那些属性。毕竟,locations
是您获取有关位置信息的地方,因此请将所有信息放在那里。在新代码中,每个locations
数组元素都有locations
属性(如果已创建标记)和marker
属性,对应于前show
数组元素。如果您不必更新单独的阵列,只需将所有信息保存在一个位置,事情就会变得更加简单。
我用boolean
替换了几个for
循环。 forEach()
接受一个回调函数,这非常好,因为在这种情况下它会为传递给回调的forEach()
参数提供一个闭包。因此,您不需要location
中的复杂代码来创建闭包 - 闭包已经存在。
我通过删除和组合重复代码来简化marker.addListener()
函数。
这就是我现在所有的时间,但我希望它会给你一些可以帮助你简化代码的东西 - 因为更简单的代码更容易理解和调试代码。
toggle()
var locations = [
{ "name": "Marari Beach Alappuzha" ,'location': { 'lat': 9.618406, 'lng': 76.340161 } },
{ "name": "Tea Mueseum" ,'location': { 'lat': 10.049198, 'lng': 77.051025 } },
{ "name": "Eravikulam National Park" ,'location': { 'lat': 10.116233, 'lng': 77.067791 } },
{ "name": "Chimmini Wildlife Sanctuary" ,'location': { 'lat': 10.428646, 'lng': 76.491031 } },
{ "name": "Bekal Fort ",'location': { 'lat': 12.440895, 'lng': 75.030311 } }
];
var map;
function initMap() {
map = new google.maps.Map( document.getElementById('map'), {
zoom: 7,
center: {
lat: 10.850516,
lng: 76.271080
}
});
var labels = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
locations.forEach( function( location ) {
var marker = location.marker = new google.maps.Marker({
position: location.location,
animation: google.maps.Animation.DROP
});
marker.addListener( 'click', function() {
if( marker.getAnimation() ) {
marker.setAnimation( null );
} else {
marker.setAnimation( google.maps.Animation.BOUNCE );
stopAnimation( marker );
}
});
function stopAnimation(marker) {
setTimeout( function() {
marker.setAnimation(null);
}, 3000 );
}
});
toggle();
}
function toggle() {
locations.forEach( function( location ) {
if( location.marker ) {
location.marker.setMap( location.show ? map : null );
}
});
}
var vm = function() {
var self = this;
self.loc = ko.observableArray( locations );
self.query = ko.observable('');
self.filteredloc = ko.computed( function () {
var z = 0;
var filter = self.query().toLowerCase();
toggle();
if( ! filter ) {
return self.loc();
} else {
return ko.utils.arrayFilter( self.loc(), function( item ) {
boolean[z] = item.name.toLowerCase().indexOf(filter) !== -1;
// console.log(boolean[z]+'in pos'+z);
z++;
return item.name.toLowerCase().indexOf(filter) !== -1;
});
}
});
}
ko.applyBindings( new vm() );