我希望能够单击标记或城市名称并弹出该特定<的info.window
em>标记
HTML:
<!DOCTYPE html>
<html>
<head>
<title>Magic Towns of Mexico</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="css/styles.css">
<style>
html,
body {
font-family: Arial, sans-serif;
height: 100%;
margin: 0;
padding: 0;
}
#map {
height: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<div class="menuContainer">
<span class="center" style="font-size:30px;cursor:pointer" onclick="openNav()">☰</span>
<div id="mySidenav" class="sidenav alignTextCenter">
<a href="javascript:void(0)" class="closebtn" onclick="closeNav()">×</a>
<a href="#"><h1>Locations:</h1></a>
<form role="search">
<input type="text" data-bind="value: query, valueUpdate: 'keyup'" placeholder="Search...">
</form>
<div data-bind='with: currentPlace' >
<div data-bind='foreach: filteredPlaces' class="alignTextCenter">
<p href="#" class="whiteFont" data-bind='text: city, click: clickSelection'></p>
</div>
</div>
</div>
</div>
<script src='js/sidebar.js'></script>
<script src="js/jquery-3.2.1.min.js"></script>
<script src="js/knockout-3.4.2.js"></script>
<script src="js/data.js"></script>
<script src="js/app2.js"></script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?libraries=geometrykey=AIzaSyBnwbuI0b5q6p5sJAa2wcHIy2DGkZFisBY&v=3&callback=initMap">
</script>
</body>
</html>
JavaScript:
var initialPlaces = [
{"city":"Tepotzotlán","lat":19.7185096,"lng":-99.2065202},
{"city":"Valle de Bravo","lat":19.1950964,"lng":-100.1326725},
{"city":"Cuitzeo","lat":19.9685057,"lng":-101.1406046},
{"city":"Pátzcuaro","lat":19.5134498,"lng":-101.6091554},
{"city":"Sta. Clara del Cobre","lat":19.4064279,"lng":-101.639697899999},
];
var map, google;
var markers = [];
var wikiElem;
var Place = function(data) {
this.city = ko.observable(data.city);
this.lat = ko.observable(data.lat);
this.lng = ko.observable(data.lng);
};
var ViewModel = function() {
var self = this;
self.placeList = ko.observableArray([]);
self.query = ko.observable(''),
initialPlaces.forEach(function(placeLocation) {
self.placeList.push( new Place(placeLocation));
});
self.currentPlace = ko.observable( this.placeList()[0]);
// Populate infowindow
this.populateInfoWindow = function(marker, infoWindow) {
if (infoWindow.marker != marker) {
infoWindow.marker = marker;
var $wikiElem = '';
var cityStr = marker.city;
var wikiUrl = 'http://en.wikipedia.org/w/api.php?action=opensearch&search=' +
cityStr + '&format=json&callback=wikiCallback';
var wikiRequestTimeOut = setTimeout(function() {
$wikiElem = 'failed to get wikipedia resources';
}, 8000);
$.ajax({
url: wikiUrl,
dataType: "jsonp",
success: function(response) {
var articleList = response[1];
for (var i = 0; i < articleList.length; i++) {
articleStr = articleList[i];
var url = 'http://en.wikipedia.org/wiki/' + articleStr;
$wikiElem += '<li><a href="' + url + '">' + articleStr + '</a></li>';
}
infoWindow.setContent(self.titleContent + '<hr>' + self.wikiTitle + $wikiElem);
clearTimeout(wikiRequestTimeOut);
}
});
self.wikiTitle = '<h3>Relevant Wikipedia Links</h3>';
self.titleContent = '<div>' + marker.city + '<div>';
infoWindow.open(map, marker);
marker.setAnimation(google.maps.Animation.BOUNCE);
setTimeout(function () {
marker.setAnimation(null);
}, 1500 );
// Cleared infowindow if is closed
infoWindow.addListener('closeclick', function() {
infoWindow.marker = null;
});
}
};
// Handles click selection on map and list
self.clickSelection = function() {
self.populateInfoWindow(this, self.largeInfoWindow);
};
// Construct Map
self.initMap = function() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 24.3001235, lng: -102.2718002},
zoom: 5,
});
var largeInfoWindow = new google.maps.InfoWindow();
// Create array for markers
for (var i = 0; i < initialPlaces.length; i++) {
this.city = initialPlaces[i].city;
this.lat = initialPlaces[i].lat;
this.lng = initialPlaces[i].lng;
// create a marker per city
this.marker = new google.maps.Marker({
map: map,
position: {lat: this.lat, lng: this.lng},
city: this.city,
icon: {
path: google.maps.SymbolPath.BACKWARD_CLOSED_ARROW,
scale: 5
},
animation: google.maps.Animation.DROP,
});
// Push the marker to our array of markers.
this.markers.push(this.marker);
this.marker.addListener('click', self.clickSelection);
}
};
self.filteredPlaces = ko.computed(function() {
if (!self.query()) {
return self.placeList();
} else {
return self.placeList()
.filter(place => place.city().toLowerCase().indexOf(self.query().toLowerCase()) > -1);
}
});
};
ko.applyBindings(ViewModel);
我希望能够单击标记来填充 info.window
,如果我单击要填充 info.window
的列表,我也希望能够单击该标记>.
我现在得到的结果是这个错误:
Uncaught TypeError: Cannot read property 'marker' of undefined at ViewModel.populateInfoWindow (app2.js:24)
最佳答案
此代码存在多个问题。
首先,对 google map api 的脚本引用有错误。它应该有
&key
而不是geometrykey
& 是因为它们是单独的参数。接下来,您的回调函数不存在。所以我创建了它。
function initMap() { var viewmodel = new ViewModel(); viewmodel.initMap(); }
initMap 方法中的这一行需要更改: var largeInfoWindow = new google.maps.InfoWindow();
在 JavaScript 中使用 var 创建一个新的局部变量。 largeInfoWindow 是 initMap 范围内的局部变量。为了使其在该范围之外可见,请将其替换为 this。
self.largeInfoWindow = new google.maps.InfoWindow();
如果您通过 http://访问您的网站,我将您的 http://wikipedia api 调用更改为 https://。但是,如果您通过 http 访问您的网站,则可以不理会它。
将来使用 jsFiddle(或类似的东西,如 codepen 或 Pastebin)可能会更容易。
关于javascript - 过滤标记并使用 knockout 和谷歌地图列出 - 未捕获的类型错误无法读取未定义的属性 'marker',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47758158/