一次显示一个信息窗口

时间:2018-01-22 20:34:16

标签: knockout.js

我有这个项目使用Google和Foursquare API显示多个位置。我能够显示位置并创建标记。我的问题是如何一次显示一个信息窗口?如果我点击新位置,则其他位置信息窗口不会关闭。现在,如果我点击一个地方和另一个地方。两个信息窗口都保持打开状态。

我的代码如下。谢谢。

var initialLocations = [{
            name: 'Golden Gate',
            lat: 37.819929,
            long: -122.478255
        }, {
            name: 'AT&T Park',
            lat: 37.7749,
            long: -122.4194

        }, {
            name: 'Twin Peaks',
            lat: 37.7544,
            long: -122.4477
        },
    ];

var clientID = "xxxxxxxxxxxxxxxxxxxxxxxxxx";
var clientSecret = "xxxxxxxxxxxxxxxxxxxxxxxx";

var Location = function(data) {
    var self = this;

    this.name = data.name;
    this.lat = data.lat;
    this.long = data.long;
    this.URL = "";
    this.street = "";
    this.city = "";
    this.phone = "";

    this.visible = ko.observable(true);

    var foursquareURL = 'https://api.foursquare.com/v2/venues/search?ll=' + this.lat + ',' + this.long + '&client_id=' + clientID + '&client_secret=' + clientSecret + '&v=20160118' + '&query=' + this.name;

    $.getJSON(foursquareURL).done(function(data) {
        var results = data.response.venues[0];
        self.URL = results.url || 'No url found';
        self.street = results.location.formattedAddress[0];
        self.city = results.location.formattedAddress[1];
        self.phone = results.contact.phone  || 'No phone found';;

    }).fail(function() {
        alert("Error found. Please refresh your page.");
    });

    // Info window


    this.infoWindow = new google.maps.InfoWindow({


    });


    // Marker

    this.marker = new google.maps.Marker({
        position: new google.maps.LatLng(data.lat, data.long),
        map: map,
        title: data.name
    });


    this.marker.addListener('click', function() {

        self.contentString = '<div class="info-window-content"><div class="title"><b>' + data.name + "</b></div>" +
            '<div class="content"><a href="' + self.URL + '">' + self.URL + "</a></div>" +
            '<div class="content">' + self.street + "</div>" +
            '<div class="content">' + self.city + "</div>" +
            '<div class="content"><a href="tel:' + self.phone + '">' + self.phone + "</a></div></div>";

        self.infoWindow.setContent(self.contentString);

        self.infoWindow.open(map, this);

        self.marker.setAnimation(google.maps.Animation.BOUNCE);
        setTimeout(function() {
            self.marker.setAnimation(null);
        }, 2100);
    });

    this.bounce = function(place) {
        google.maps.event.trigger(self.marker, 'click');
    };
};


//-ViewModel
function AppViewModel() {
    var self = this;

    // create array of places

    this.locationList = ko.observableArray([]);
    this.searchLocation = ko.observable('');

    map = new google.maps.Map(document.getElementById('map'), {
        zoom: 12,
        center: {
            lat: 37.77986,
            lng: -122.429
        }
    });

    initialLocations.forEach(function(locationItem) {
        self.locationList.push(new Location(locationItem));
    });

    this.filteredList = ko.computed(function() {
        var filter = self.searchLocation().toLowerCase();
        if (!filter) {
            self.locationList().forEach(function(locationItem) {
                locationItem.visible(true);
            });
            return self.locationList();
        } else {
            return ko.utils.arrayFilter(self.locationList(), function(locationItem) {
                var string = locationItem.name.toLowerCase();
                var result = (string.search(filter) >= 0);
                locationItem.visible(result);
                return result;
            });
        }
    }, self);

    this.mapElem = document.getElementById('map');
    this.mapElem.style.height = window.innerHeight - 50;
}
// Bind the VeiewModel to the view using knockout
function startApp() {
    ko.applyBindings(new AppViewModel());
}

function errorHandling() {
    alert("Error loading page, try refresh in page.");
}

2 个答案:

答案 0 :(得分:0)

  1. 您必须创建一个全局变量,以保存正在显示的infoWindow:

    var infowindow = null;

  2. 每当你去展示一个infowindow时,你会检查它是否为空,然后你关闭它。

    if(infowindow){     infowindow.close(); }

  3. 然后创建一个新实例并将其分配给变量:

    infowindow = new google.maps.InfoWindow(); ...

  4. 如果您有任何疑问,请写信给我,我会帮助您。

    原谅我的英文

    在这里您可以找到更多答案: Close all infowindows in Google Maps API v3

答案 1 :(得分:0)

您可以与所有infoWindow个对象共享Location。您需要将infoWindowLocation移至AppViewModel,才能拥有此对象的实例。

然后,AppViewModel应为:

//-ViewModel
function AppViewModel() {
    var self = this;

    // create array of places

    this.locationList = ko.observableArray([]);
    this.searchLocation = ko.observable('');

    var map = new google.maps.Map(document.getElementById('map'), {
        zoom: 12,
        center: {
            lat: 37.77986,
            lng: -122.429
        }
    });

    // ** Move the infoWindow from Location to AppViewModel.    
    var infoWindow = new google.maps.InfoWindow({
    });


    initialLocations.forEach(function(locationItem) {
        // To each Location object, pass the same infoWindow object
        self.locationList.push(new Location(locationItem, infoWindow, map));
    });

    // from here, the same code you have in AppViewModel
    ...
}

现在向Location函数(对象)添加一个参数:

function Location(data, infoWindow, map) {

评论infoWindow(或删除它,因为你将它作为参数):

    //// Info window
    //this.infoWindow = new google.maps.InfoWindow({
    //});

更改click听众:

    this.marker.addListener('click', function() {

        self.contentString = '<div class="info-window-content"><div class="title"><b>' + data.name + "</b></div>" +
            '<div class="content"><a href="' + self.URL + '">' + self.URL + "</a></div>" +
            '<div class="content">' + self.street + "</div>" +
            '<div class="content">' + self.city + "</div>" +
            '<div class="content"><a href="tel:' + self.phone + '">' + self.phone + "</a></div></div>";

        // ** Here, remove the 'self' in order to use the infoWindow received as parameter.
        infoWindow.setContent(self.contentString);

        // ** Here, remove the 'self' in order to use the infoWindow received as parameter.
        infoWindow.open(map, this);

        self.marker.setAnimation(google.maps.Animation.BOUNCE);
        setTimeout(function() {
            self.marker.setAnimation(null);
        }, 2100);
    });

这样,您的所有Location对象都会看到相同的infoWindow对象。只有一个infoWindow

<强>更新 至于评论,我看到map成为全局变量。它在AppViewModel()中声明,但应使用varlet声明。我改变了它的定义。

然后,我们应该向Location对象(地图)添加一个新参数,因为现在不是全局变量。