javascript - 按类别选择标记并适应可见标记

标签 javascript google-maps google-maps-api-3 google-maps-markers

我有一个按类别切换标记可见性的代码,效果很好(请参见下面的代码)。

我现在想添加但不知道如何添加:

每次显示/隐藏标记组后,我希望调整 map 的缩放和中心以显示所有可见标记。
我找到了另一个代码 fitBounds() ,但无法让两者一起工作(我对 Javascript 完全陌生)。

我发现了仅将边界拟合到可见标记的示例,但没有与按类别显示/隐藏标记相结合。 (例如Center/Set Zoom of Map to cover all visible Markers?)

这里有两个代码示例:

按类别显示/隐藏标记:

function xmlParse(str) {
    if (typeof ActiveXObject != 'undefined' && typeof GetObject != 'undefined') {
        var doc = new ActiveXObject('Microsoft.XMLDOM');
        doc.loadXML(str);
        return doc;
    }

    if (typeof DOMParser != 'undefined') {
        return (new DOMParser()).parseFromString(str, 'text/xml');
    }

    return createElement('div', null);
}
var infoWindow = new google.maps.InfoWindow();
var customIcons = {
    monumento: {
        icon: 'http://maps.google.com/mapfiles/ms/icons/blue.png'
    },
    hotel: {
        icon: 'http://maps.google.com/mapfiles/ms/icons/green.png'
    },
    restaurantes: {
        icon: 'http://maps.google.com/mapfiles/ms/icons/yellow.png'
    },
    museus: {
        icon: 'http://maps.google.com/mapfiles/ms/icons/purple.png'
    }
};

var markerGroups = {
    "museus": [],
    "monumentos": [],
    "restaurantes": [],
    "hotel": []
};

function load() {
    var map = new google.maps.Map(document.getElementById("mapCanvas"), {
        center: new google.maps.LatLng(38.639104, -8.210413),
        zoom: 12,
        mapTypeId: 'satellite'
    });
    var infoWindow = new google.maps.InfoWindow();



    map.set('styles', [{
        zoomControl: false
    }, {
        featureType: "road.highway",
        elementType: "geometry.fill",
        stylers: [{
            color: "#ffd986"
        }]
    }, {
        featureType: "road.arterial",
        elementType: "geometry.fill",
        stylers: [{
            color: "#9e574f"
        }]
    }, {
        featureType: "road.local",
        elementType: "geometry.fill",
        stylers: [{
                color: "#d0cbc0"
            }, {
                weight: 1.1
            }

        ]
    }, {
        featureType: 'road',
        elementType: 'labels',
        stylers: [{
            saturation: -100
        }]
    }, {
        featureType: 'landscape',
        elementType: 'geometry',
        stylers: [{
            hue: '#ffff00'
        }, {
            gamma: 1.4
        }, {
            saturation: 82
        }, {
            lightness: 96
        }]
    }, {
        featureType: 'poi.school',
        elementType: 'geometry',
        stylers: [{
            hue: '#fff700'
        }, {
            lightness: -15
        }, {
            saturation: 99
        }]
    }]);

    //         downloadUrl("markers.xml", function (data) {
    var xml = xmlParse('<markers><marker name="Castelo" address="Rua da Condessa de Valença" lat="38.64351973190569" lng="-8.216521812152905" type="monumento" /><marker name="Anta 1 de Tourais" address="Estrada Nacional 114" lat="38.64260059929888" lng="-8.159376865959189" type="monumento" /><marker name="Hotel da Ameira" address="Herdade da Ameira" lat="38.64109640475479" lng="-8.180432206726096" type="hotel" /><marker name="Hotel Montemor" address="Avenida Gago Coutinho 8, 7050-248 Montemor-o-Novo" lat="38.64925541964039" lng="-8.216489625644726" type="hotel" /><marker name="Restaurante Monte Alentejano" address="Av. Gago Coutinho 8" lat="38.6492329" lng="-8.216665" type="restaurantes" /><marker name="Restaurante A Ribeira" address="Rua de São Domingos" lat="38.6347498199708" lng="-8.206468892765088" type="restaurantes" /><marker name="Núcleo Museológico do Convento de S. Domingos" address="" lat="38.643139" lng="-8.212732" type="museus" /><marker name="Centro Interpretativo do Castelo de Montemor-o-Novo" address="Rua Condessa de Valença" lat="38.64258748216167" lng="-8.21467108793263" type="museus" /></markers>');
    // var xml = data.responseXML;
    var markers = xml.documentElement.getElementsByTagName("marker");
    for (var i = 0; i < markers.length; i++) {
        var name = markers[i].getAttribute("name");
        var address = markers[i].getAttribute("address");
        var type = markers[i].getAttribute("type");

        var point = new google.maps.LatLng(
            parseFloat(markers[i].getAttribute("lat")),
            parseFloat(markers[i].getAttribute("lng")));
        var html = "<b>" + name + "</b> <br/>" + address;
        // var icon = customIcons[type] || {};
        var marker = createMarker(point, name, address, type, map);
        bindInfoWindow(marker, map, infoWindow, html);
    }
    // });
}

function createMarker(point, name, address, type, map) {
    var icon = customIcons[type] || {};
    var marker = new google.maps.Marker({
        map: map,
        position: point,
        icon: icon.icon,
        // shadow: icon.shadow,
        type: type
    });
    if (!markerGroups[type]) markerGroups[type] = [];
    markerGroups[type].push(marker);
    var html = "<b>" + name + "</b> <br/>" + address;
    bindInfoWindow(marker, map, infoWindow, html);
    return marker;
}

function toggleGroup(type) {
    for (var i = 0; i < markerGroups[type].length; i++) {
        var marker = markerGroups[type][i];
        if (!marker.getVisible()) {
            marker.setVisible(true);
        } else {
            marker.setVisible(false);
        }
    }
}


function bindInfoWindow(marker, map, infoWindow, html) {
    google.maps.event.addListener(marker, 'click', function() {
        infoWindow.setContent(html);
        infoWindow.open(map, marker);

    });
}

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, request.status);
        }
    };

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

function doNothing() {}
google.maps.event.addDomListener(window, 'load', load);

fitBounds() 到可见标记:

function fitBoundsToVisibleMarkers() {

   var bounds = new google.maps.LatLngBounds();

   for (var i = 0; i < markers.length; i++) {
       if (markers[i].getVisible()) {
           bounds.extend(markers[i].getPosition());
       }
   }

   map.fitBounds(bounds);
}

最佳答案

您的代码存在一些问题:

  1. 您遇到错误:未捕获类型错误:map.fitBounds 不是函数。这是因为您需要在函数 load 之外设置 map 变量。
  2. 您需要收集所有可见标记,然后对它们运行 map.fitBounds

工作代码:

function xmlParse(str) {
  if (typeof ActiveXObject != 'undefined' && typeof GetObject != 'undefined') {
    var doc = new ActiveXObject('Microsoft.XMLDOM');
    doc.loadXML(str);
    return doc;
  }

  if (typeof DOMParser != 'undefined') {
    return (new DOMParser()).parseFromString(str, 'text/xml');
  }

  return createElement('div', null);
}
var infoWindow = new google.maps.InfoWindow();
var customIcons = {
  monumento: {
    icon: 'http://maps.google.com/mapfiles/ms/icons/blue.png'
  },
  hotel: {
    icon: 'http://maps.google.com/mapfiles/ms/icons/green.png'
  },
  restaurantes: {
    icon: 'http://maps.google.com/mapfiles/ms/icons/yellow.png'
  },
  museus: {
    icon: 'http://maps.google.com/mapfiles/ms/icons/purple.png'
  }
};

var markerGroups = {
  "museus": [],
  "monumentos": [],
  "restaurantes": [],
  "hotel": []
};

var ctr = new google.maps.LatLng(38.639104, -8.210413),
    zoom = 12;

var map;
function load() {
  map = new google.maps.Map(document.getElementById("map"), {
    center: ctr,
    zoom: zoom,
    mapTypeId: 'roadmap'
  });

  var infoWindow = new google.maps.InfoWindow();

  map.set('styles', [{
    zoomControl: false
  }, {
    featureType: "road.highway",
    elementType: "geometry.fill",
    stylers: [{
      color: "#ffd986"
    }]
  }, {
    featureType: "road.arterial",
    elementType: "geometry.fill",
    stylers: [{
      color: "#9e574f"
    }]
  }, {
    featureType: "road.local",
    elementType: "geometry.fill",
    stylers: [{
      color: "#d0cbc0"
    }, {
      weight: 1.1
    }]
  }, {
    featureType: 'road',
    elementType: 'labels',
    stylers: [{
      saturation: -100
    }]
  }, {
    featureType: 'landscape',
    elementType: 'geometry',
    stylers: [{
      hue: '#ffff00'
    }, {
      gamma: 1.4
    }, {
      saturation: 82
    }, {
      lightness: 96
    }]
  }, {
    featureType: 'poi.school',
    elementType: 'geometry',
    stylers: [{
      hue: '#fff700'
    }, {
      lightness: -15
    }, {
      saturation: 99
    }]
  }]);

  //         downloadUrl("markers.xml", function (data) {
  var xml = xmlParse('<markers><marker name="Castelo" address="Rua da Condessa de Valença" lat="38.64351973190569" lng="-8.216521812152905" type="monumento" /><marker name="Anta 1 de Tourais" address="Estrada Nacional 114" lat="38.64260059929888" lng="-8.159376865959189" type="monumento" /><marker name="Hotel da Ameira" address="Herdade da Ameira" lat="38.64109640475479" lng="-8.180432206726096" type="hotel" /><marker name="Hotel Montemor" address="Avenida Gago Coutinho 8, 7050-248 Montemor-o-Novo" lat="38.64925541964039" lng="-8.216489625644726" type="hotel" /><marker name="Restaurante Monte Alentejano" address="Av. Gago Coutinho 8" lat="38.6492329" lng="-8.216665" type="restaurantes" /><marker name="Restaurante A Ribeira" address="Rua de São Domingos" lat="38.6347498199708" lng="-8.206468892765088" type="restaurantes" /><marker name="Núcleo Museológico do Convento de S. Domingos" address="" lat="38.643139" lng="-8.212732" type="museus" /><marker name="Centro Interpretativo do Castelo de Montemor-o-Novo" address="Rua Condessa de Valença" lat="38.64258748216167" lng="-8.21467108793263" type="museus" /></markers>');
  // var xml = data.responseXML;
  var markers = xml.documentElement.getElementsByTagName("marker");
  for (var i = 0; i < markers.length; i++) {
    var name = markers[i].getAttribute("name");
    var address = markers[i].getAttribute("address");
    var type = markers[i].getAttribute("type");

    var point = new google.maps.LatLng(
      parseFloat(markers[i].getAttribute("lat")),
      parseFloat(markers[i].getAttribute("lng")));
    var html = "<b>" + name + "</b> <br/>" + address;
    // var icon = customIcons[type] || {};
    var marker = createMarker(point, name, address, type, map);
    bindInfoWindow(marker, map, infoWindow, html);
  }
  // });
  //fitMap();
}

function createMarker(point, name, address, type, map) {
  var icon = customIcons[type] || {};
  var marker = new google.maps.Marker({
    map: map,
    position: point,
    icon: icon.icon,
    // shadow: icon.shadow,
    type: type,
    visible:false
  });
  if (!markerGroups[type]) markerGroups[type] = [];
  markerGroups[type].push(marker);
  var html = "<b>" + name + "</b> <br/>" + address;
  bindInfoWindow(marker, map, infoWindow, html);
  return marker;
}

function toggleGroup(type) {
  for (var i = 0; i < markerGroups[type].length; i++) {
    var marker = markerGroups[type][i];
    if (!marker.getVisible()) {
      marker.setVisible(true);
    } else {
      marker.setVisible(false);
    }
  }

  if (document.querySelectorAll(':checked').length == 0) {
    map.setCenter(ctr);
    map.setZoom(zoom);
  }
  else {
    fitMap();
  }
}


function fitMap() {
  var visibleMarkers = [];
  for (var i in markerGroups) {
    for (var j = 0; j < markerGroups[i].length; j++) {
      var marker = markerGroups[i][j];
      if (marker.getVisible()) {
        visibleMarkers.push(marker);
      }
    }
  }

  var bounds = new google.maps.LatLngBounds();
  for (var i = 0; i < visibleMarkers.length; i++) {
    bounds.extend(visibleMarkers[i].getPosition());
  }

  map.fitBounds(bounds);  
}

function bindInfoWindow(marker, map, infoWindow, html) {
  google.maps.event.addListener(marker, 'click', function () {
    infoWindow.setContent(html);
    infoWindow.open(map, marker);
  });
}

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, request.status);
    }
  };

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

function doNothing() {}
google.maps.event.addDomListener(window, 'load', load);
html, body, #map, #map_wrap {
  height: 100%;
  width:100%;
}
<script src="https://maps.googleapis.com/maps/api/js?v=3&ext=.js"></script>
<div class="map_wrap">
  <div class="siderbarmap">
    <ul>
      <input id="monumentoCheckbox" type="checkbox" onclick="toggleGroup('monumento')" />
      <input id="museusCheckbox" type="checkbox" onclick="toggleGroup('museus')"  />
      <input id="restaurantesCheckbox" type="checkbox" onclick="toggleGroup('restaurantes')" />
      <input id="hotelCheckbox" type="checkbox" onclick="toggleGroup('hotel')" />
    </ul>
  </div>
  <div id="map" style="width:100%;height:585px; z-index: 1;"></div>
</div>

更新:

  1. 我稍微更改了代码,所以现在查找可见标记的函数是独立的,因此我们可以在页面加载中以及更改复选框后调用它(现在在要求 2 的注释中。要使用它,只需删除评论 //)。
  2. 在用户点击复选框后,开始时所有标记都不可见
  3. 如果没有:checked复选框, map 将重置为起始缩放中心

关于javascript - 按类别选择标记并适应可见标记,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34974479/

相关文章:

javascript - 在 Javascript 中哪里添加 onsubmit 到表单

javascript - 当我想用nodejs进行mysql插入时,为什么会出现解析错误

google-maps - 确定 Google Maps API key 的使用

google-maps - Google 静态 map - 画一个圆圈

php - 无法在 javascript 循环中增加 php 变量以在谷歌地图上绘制多边形

javascript - 尝试从 Django 服务器设置值时,Java 脚本给出无效的语法错误

javascript - jQuery 脚本无法处理从另一个页面附加的 html

android - java.lang.ClassCastException : android. support.v4.app.NoSaveStateFrameLayout 无法转换为 com.google.android.maps.MapView

javascript - 向谷歌地图 API 发送请求

javascript - 使用 AngularJS 在 Google map 中实现标记