使用Google Maps API v3禁用兴趣点信息窗口

55

我有一个带有信息气泡和自定义标记的自定义地图。当我缩放到兴趣点(如公园和大学)时,它们会出现,并且当我点击时,信息窗口会打开。如何禁用信息窗口?

我的代码如下:

var geocoder;
var map;
var infoBubble;
var dropdown = "";
var gmarkers = [];

var hostel_icon = new google.maps.MarkerImage('/resources/hostel_blue_icon.png',
new google.maps.Size(28,32),
new google.maps.Point(0,0),
new google.maps.Point(14,32));

var bar_icon = new google.maps.MarkerImage('/resources/bar_red_icon.png',
new google.maps.Size(28,32),
new google.maps.Point(0,0),
new google.maps.Point(14,32));

var icon_shadow = new google.maps.MarkerImage('/resources/myicon_shadow.png',
new google.maps.Size(45,32),
new google.maps.Point(0,0),
new google.maps.Point(12,32));

var customIcons = {
    hostel: {
        icon: hostel_icon,
        shadow: icon_shadow
    },
    bar: {
        icon: bar_icon,
        shadow: icon_shadow
    }
};

function initialize() {
    var latlng = new google.maps.LatLng(12.82364, 26.29987);
    var myMapOptions = {
        zoom: 2,
        center: latlng,
        panControl: false,
        scaleControl: true,
        mapTypeId: google.maps.MapTypeId.TERRAIN,
        mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.HORIZONTAL_BAR},
        navigationControlOptions: {style: google.maps.NavigationControlStyle.DEFAULT}
    }
    map = new google.maps.Map(document.getElementById("map_canvas"), myMapOptions);

    infoBubble = new InfoBubble({
        shadowStyle: 0,
        padding: 0,
        backgroundColor: 'rgb(57,57,57)',
        borderRadius: 5,
        arrowSize: 10,
        borderWidth: 1,
        maxWidth: 400,
        borderColor: '#2c2c2c',
        disableAutoPan: false,
        hideCloseButton: true,
        arrowPosition: 50,
        backgroundClassName: 'phoney',
        arrowStyle: 0
    });

    // Change this depending on the name of your PHP file
    downloadUrl("phpsqlajax_genxml_2.php", function(data) {
        var xml = parseXml(data);
        var markers = xml.documentElement.getElementsByTagName("marker");
        for (var i = 0; i < markers.length; i++) {
            var bar_name = markers[i].getAttribute("bar_name");
            var hostel_name = markers[i].getAttribute("hostel_name");
            var street = markers[i].getAttribute("street");
            var city = markers[i].getAttribute("city");
            var postcode = markers[i].getAttribute("postcode");
            var country = markers[i].getAttribute("country");
            var page = markers[i].getAttribute("page");
            var map_photo = markers[i].getAttribute("map_photo");
            var type = markers[i].getAttribute("type");
            var category = markers[i].getAttribute("category");
            var point = new google.maps.LatLng(
            parseFloat(markers[i].getAttribute("lat")),
            parseFloat(markers[i].getAttribute("lng")));

            var html = '<div class="infowindow"><div class="iwPhoto" style="width: 105px; height: 65px;">' + "<a href='" + page + "'><img src='" + map_photo + "' alt=''/></a>" + '</div><div class="iwName" style="height: 24px;">' + "<a href='" + page + "'>" + hostel_name + "</a>" + '</div><div class="iwCategory" style="height: 15px;">' + category + '</div><div class="iwCity" style="height: 29px;">' + "<a href='" + page + "'>" + city + "</a>" + '<div class="iwArrow" style="width: 29px; height: 29px;">' + "<a href='" + page + "'><img src='/resources/arrow.png'/></a>" + '</div></div></div>';

            var icon = customIcons[type] || {};
            var marker = new google.maps.Marker({
                map: map,
                position: point,
                icon: icon.icon,
                shadow: icon.shadow,
                title: bar_name
            });
            marker.bar_name = bar_name;
            marker.category = category;
            bindInfoBubble(marker, map, infoBubble, html, bar_name);

            gmarkers.push(marker);

            str = '<option selected> - Select a club - </option>';
            for (j=0; j < gmarkers.length; j++){
                str += '<option value="'+gmarkers[j].bar_name+'">'+gmarkers[j].bar_name+', '+gmarkers[j].category+'</option>';
            }
            var str1 ='<form name="form_city" action=""><select style="width:150px;" id="select_city" name="select_cityUrl" onchange="handleSelected(this);">';
            var str2 ='</select></form>';
            dropdown = str1 + str + str2;
        }
        document.getElementById("dd").innerHTML = dropdown;
    });
}

function handleSelected(opt) {
    var indexNo = opt[opt.selectedIndex].index;
    google.maps.event.trigger(gmarkers[indexNo-1], "click");
}

function bindInfoBubble(marker, map, infoBubble, html) {
    google.maps.event.addListener(marker, 'click', function() {
        infoBubble.setContent(html);
        infoBubble.open(map, marker);
        google.maps.event.addListener(map, "click", function () {
            infoBubble.close();
        });
    });
}

function downloadUrl(url, callback) {
    var request = window.ActiveXObject ?
                  new ActiveXObject('Microsoft.XMLHTTP') :
                  new XMLHttpRequest;

    request.onreadystatechange = function() {
        if (request.readyState == 4) {
            request.onreadystatechange = doNothing;
            callback(request.responseText, request.status);
        }
    };

    request.open('GET', url, true);
    request.send(null);
}

function parseXml(str) {
    if (window.ActiveXObject) {
        var doc = new ActiveXObject('Microsoft.XMLDOM');
        doc.loadXML(str);
        return doc;
    } else if (window.DOMParser) {
        return (new DOMParser).parseFromString(str, 'text/xml');
    }
}

function doNothing() {}

2
这就是答案:可以将其设置为MapOptions对象上的“styles”选项,这将应用于路线图、混合和地形地图类型。要使用的正确样式是: [ { featureType: "poi", elementType: "labels", stylers: [ { visibility: "off" } ] } ] - Brendon
2
这并不是真正的答案,因为它完全移除了地图上的标签。你如何保留标签但禁用信息窗口呢? - James
7个回答

84

@brendon 如果您将此选为正确答案,对其他用户会非常有帮助。这样我们就不需要滚动查找过于复杂的解决方案,而是可以通过 API 提供的单个标志找到真正的解决方案。 - Tyler Kemme
这就是为什么我总是滚动超过3个答案。这非常有效!谢谢分享 :D - Ken Nguyen
这个链接对我有效:https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.clickableIcons - MrYellow

38

如果您想要可点击但没有信息窗口, 可以在event上调用stop()来防止信息窗口出现,但仍然可以获取位置信息。请参见其他答案以获取不可点击的答案。

map.addListener('click', function (event) {
  // If the event is a POI
  if (event.placeId) {

    // Call event.stop() on the event to prevent the default info window from showing.
    event.stop();

    // do any other stuff you want to do
    console.log('You clicked on place:' + event.placeId + ', location: ' + event.latLng);
  }
}

更多信息请参见文档.


另一种选择:完全移除POI图标,而不仅仅是信息窗口:

var mapOptions = {
  styles: [{ featureType: "poi", elementType: "labels", stylers: [{ visibility: "off" }]}]
};
var map = new google.maps.Map(document.getElementById('map-canvas'),
    mapOptions);

也许你收到了负评是因为你的回答是错误的。谷歌实际上允许删除POI。我刚刚做到了: styles: [{ featureType: "poi", elementType: "labels", stylers: [{ visibility: "off" }]}] - HerrimanCoder
5
问题是:“如何禁用POI的信息窗口”,而不是“如何完全禁用POI图标”。你的代码完全禁用了POI。 - Arjan
我不介意POI,但我允许用户在地图上放置标记。当他们单击POI时,它从未注册我的点击事件。我使用google.maps.event.addListener来实现这一点。为什么它不会在POI点击时触发? - Leeish
'placeId' in event 是一个更好的选择,而不是 event.placeId,因为 TypeScript 不会报错。 - Akxe

13
您可以通过创建一个没有兴趣点标签的样式地图来实现这一点。这将保留地图的地形和其他有用信息,但删除标记。
  var remove_poi = [
    {
      "featureType": "poi",
      "elementType": "labels",
      "stylers": [
        { "visibility": "off" }
      ]
    }
  ]

map.setOptions({styles: remove_poi})

太棒了!非常感谢你! - user664833
2
这对我没有任何作用。但是这个有效:styles: [{ featureType: "poi", elementType: "labels", stylers: [{ visibility: "off" }]}] - HerrimanCoder

8
您可以考虑以下方法来禁用POI信息窗口:
function disablePOIInfoWindow(){
    var fnSet = google.maps.InfoWindow.prototype.set;
    google.maps.InfoWindow.prototype.set = function () {
    };
}

示例

function initMap() {
    var latlng = new google.maps.LatLng(40.713638, -74.005529);
    var myOptions = {
        zoom: 17,
        center: latlng,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    
    var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
    disablePOIInfoWindow();  
}

function disablePOIInfoWindow(){
    var fnSet = google.maps.InfoWindow.prototype.set;
    google.maps.InfoWindow.prototype.set = function () {
       alert('Ok');
    };
}


google.maps.event.addDomListener(window, 'load', initMap);
html, body {
   height: 100%;
   margin: 0;
   padding: 0;
}

#map_canvas {
   height: 100%;
}
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<div id="map_canvas"></div>

上面的示例会影响所有信息窗口,所以如果您只需要禁用POI信息窗口,则可以引入标志来确定它是否为POI信息窗口:
function disablePOIInfoWindow(){
    var fnSet = google.maps.InfoWindow.prototype.set;
    google.maps.InfoWindow.prototype.set = function () {
        if(this.get('isCustomInfoWindow'))
           fnSet.apply(this, arguments);
    };
}

示例

function initMap() {
    var latlng = new google.maps.LatLng(40.713638, -74.005529);
    var myOptions = {
        zoom: 17,
        center: latlng,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    var infowindow = new google.maps.InfoWindow({
        content: ''
    });
    infowindow.set('isCustomInfoWindow',true);
    var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
    disablePOIInfoWindow();
    google.maps.event.addListener(map, 'click', function (event) {
        infowindow.setContent(event.latLng.lat() + "," + event.latLng.lng());
        infowindow.setPosition(event.latLng);
        infowindow.open(map, this);
    });
    
}

function disablePOIInfoWindow(){
    var fnSet = google.maps.InfoWindow.prototype.set;
    google.maps.InfoWindow.prototype.set = function () {
        if(this.get('isCustomInfoWindow'))
           fnSet.apply(this, arguments);
    };
}


//google.maps.event.addDomListener(window, 'load', initMap);
html, body {
   height: 100%;
   margin: 0;
   padding: 0;
}

#map_canvas {
   height: 100%;
}
<div id="map_canvas"></div>
<script src="https://maps.googleapis.com/maps/api/js?callback=initMap"
            async defer></script>


2

只需将地图样式设置为不显示兴趣点即可。这很简单,不会违反Google的服务条款。

例如:

mapOpts = {
  styles: [
    {
      featureType: "poi",
      stylers: [
         visibility: "off"
      ]
    }
  ]
};

$("#my-map").gmap(mapOpts).on("init", function(evt, map){
  // do stuff with the initialised map
});

1

我们可以通过处理POI上的点击来实现,Google api提供了一种检测POI点击的方法,参见article

基于上述文章,以下是一个更简单的代码版本,可用于停止POI上的点击。

function initMap() {
    map = new google.maps.Map(document.getElementById('map'), myOptions);
    var clickHandler = new ClickEventHandler(map, origin);
}


var ClickEventHandler = function (map, origin) {
    this.origin = origin;
    this.map = map;
    this.map.addListener('click', this.handleClick.bind(this));
};

ClickEventHandler.prototype.handleClick = function (event) {
    //console.log('You clicked on: ' + event.latLng);
    if (event.placeId) {
        //console.log('You clicked on place:' + event.placeId);
        // Calling e.stop() on the event prevents the default info window from
        // showing.
        // If you call stop here when there is no placeId you will prevent some
        // other map click event handlers from receiving the event.
        event.stop();

    }
}

已经有很多不错的解决方案可以正常工作,请查看它们。您认为您的答案是否为此帖子增加了一些重要信息或质量? - L. Guthardt

0
如果您想要获取数据而不显示InfoWindow HTML,您只需要重新设计google.maps.InfoWindow的原型即可:
google.maps.InfoWindow.prototype.open = function () {
  return this; //prevent InfoWindow to appear
}
google.maps.InfoWindow.prototype.setContent = function (content) {
  if (content.querySelector) {
    var addressHTML = content.querySelector('.address');
    var address = addressHTML.innerHTML.replace(/<[^>]*>/g, ' ').trim();
    var link = content.querySelector('a').getAttribute('href');
    var payload = {
      header: 'event',
      eventName: 'place_picked',
      data: {
        name: content.querySelector('.title').innerHTML.trim(),
        address: address,
        link: link
      }
    };
    console.log('emit your event/call your function', payload);
  }
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接