이것에 비트가 붙어 있습니다. JSON을 통해 지리적 좌표 목록을 검색하고 Google지도에 표시합니다. 정확히 같은 지점에 두 개 이상의 마커가있는 경우를 제외하고는 모두 잘 작동합니다. API는 맨 위의 마커 1 개만 표시합니다. 이것은 내가 생각하기에 충분히 공평하지만 어떻게 든 그들을 모두 표시하는 방법을 찾고 싶습니다.
Google을 검색하고 몇 가지 솔루션을 찾았지만 대부분 API의 V2 용이거나 그다지 좋지 않은 것 같습니다. 이상적으로는 일종의 그룹 마커를 클릭 한 다음 마커가 모두있는 지점 주변에 클러스터 된 마커를 표시하는 솔루션을 원합니다.
누구든지이 문제가 있거나 비슷한 문제가 있었고 해결책을 공유하고 싶습니까?
답변
OverlappingMarkerSpiderfier를 살펴보십시오 .
데모 페이지가 있지만 정확히 같은 지점에있는 마커는 표시되지 않고 서로 매우 가까운 마커 만 표시됩니다.
그러나 똑같은 지점에 마커가있는 실제 사례는 http://www.ejw.de/ejw-vor-ort/에서 볼 수 있습니다 (지도를 아래로 스크롤하고 몇 개의 마커를 클릭하여 거미 효과를 볼 수 있습니다. ).
그것은 당신의 문제에 대한 완벽한 해결책 인 것 같습니다.
답변
마커가 같은 건물에있는 경우 마커 오프셋은 실제 솔루션이 아닙니다. 원하는 것은 markerclusterer.js를 다음과 같이 수정하는 것입니다.
-
MarkerClusterer 클래스에 프로토 타입 클릭 메소드를 다음과 같이 추가합니다. 나중에 map initialize () 함수에서이를 재정의합니다.
MarkerClusterer.prototype.onClick = function() { return true; };
-
ClusterIcon 클래스에서 clusterclick 트리거 후에 다음 코드를 추가합니다.
// Trigger the clusterclick event. google.maps.event.trigger(markerClusterer, 'clusterclick', this.cluster_); var zoom = this.map_.getZoom(); var maxZoom = markerClusterer.getMaxZoom(); // if we have reached the maxZoom and there is more than 1 marker in this cluster // use our onClick method to popup a list of options if (zoom >= maxZoom && this.cluster_.markers_.length > 1) { return markerClusterer.onClickZoom(this); }
-
그런 다음지도를 초기화하고 MarkerClusterer 객체를 선언하는 initialize () 함수에서 다음을 수행합니다.
markerCluster = new MarkerClusterer(map, markers); // onClickZoom OVERRIDE markerCluster.onClickZoom = function() { return multiChoice(markerCluster); }
multiChoice ()는 선택할 수있는 옵션 목록이있는 InfoWindow를 팝업하는 (아직 작성되지 않은) 함수입니다. markerClusterer 객체는 해당 클러스터에있는 마커 수를 확인하는 데 필요하므로 함수에 전달됩니다. 예를 들면 :
function multiChoice(mc) { var cluster = mc.clusters_; // if more than 1 point shares the same lat/long // the size of the cluster array will be 1 AND // the number of markers in the cluster will be > 1 // REMEMBER: maxZoom was already reached and we can't zoom in anymore if (cluster.length == 1 && cluster[0].markers_.length > 1) { var markers = cluster[0].markers_; for (var i=0; i < markers.length; i++) { // you'll probably want to generate your list of options here... } return false; } return true; }
답변
나는 이것을 jQuery와 함께 사용했으며 작업을 수행합니다.
var map;
var markers = [];
var infoWindow;
function initialize() {
var center = new google.maps.LatLng(-29.6833300, 152.9333300);
var mapOptions = {
zoom: 5,
center: center,
panControl: false,
zoomControl: false,
mapTypeControl: false,
scaleControl: false,
streetViewControl: false,
overviewMapControl: false,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
$.getJSON('jsonbackend.php', function(data) {
infoWindow = new google.maps.InfoWindow();
$.each(data, function(key, val) {
if(val['LATITUDE']!='' && val['LONGITUDE']!='')
{
// Set the coordonates of the new point
var latLng = new google.maps.LatLng(val['LATITUDE'],val['LONGITUDE']);
//Check Markers array for duplicate position and offset a little
if(markers.length != 0) {
for (i=0; i < markers.length; i++) {
var existingMarker = markers[i];
var pos = existingMarker.getPosition();
if (latLng.equals(pos)) {
var a = 360.0 / markers.length;
var newLat = pos.lat() + -.00004 * Math.cos((+a*i) / 180 * Math.PI); //x
var newLng = pos.lng() + -.00004 * Math.sin((+a*i) / 180 * Math.PI); //Y
var latLng = new google.maps.LatLng(newLat,newLng);
}
}
}
// Initialize the new marker
var marker = new google.maps.Marker({map: map, position: latLng, title: val['TITLE']});
// The HTML that is shown in the window of each item (when the icon it's clicked)
var html = "<div id='iwcontent'><h3>"+val['TITLE']+"</h3>"+
"<strong>Address: </strong>"+val['ADDRESS']+", "+val['SUBURB']+", "+val['STATE']+", "+val['POSTCODE']+"<br>"+
"</div>";
// Binds the infoWindow to the point
bindInfoWindow(marker, map, infoWindow, html);
// Add the marker to the array
markers.push(marker);
}
});
// Make a cluster with the markers from the array
var markerCluster = new MarkerClusterer(map, markers, { zoomOnClick: true, maxZoom: 15, gridSize: 20 });
});
}
function markerOpen(markerid) {
map.setZoom(22);
map.panTo(markers[markerid].getPosition());
google.maps.event.trigger(markers[markerid],'click');
switchView('map');
}
google.maps.event.addDomListener(window, 'load', initialize);
답변
Chaoley의 답변을 확장하여 좌표가 정확히 동일한 위치 ( lng
및 lat
속성이있는 객체) 목록이 주어지면 원래 위치에서 약간 이동 (객체를 제자리에서 수정)하는 기능을 구현했습니다. 그런 다음 중심점 주위에 멋진 원을 형성합니다.
위도 (북위 52도)의 경우 0.0003 도의 원 반경이 가장 적합하며 킬로미터로 변환 할 때 위도와 경도의 차이를 보상해야한다는 것을 알았습니다. 여기에서 위도에 대한 대략적인 변환을 찾을 수 있습니다 .
var correctLocList = function (loclist) {
var lng_radius = 0.0003, // degrees of longitude separation
lat_to_lng = 111.23 / 71.7, // lat to long proportion in Warsaw
angle = 0.5, // starting angle, in radians
loclen = loclist.length,
step = 2 * Math.PI / loclen,
i,
loc,
lat_radius = lng_radius / lat_to_lng;
for (i = 0; i < loclen; ++i) {
loc = loclist[i];
loc.lng = loc.lng + (Math.cos(angle) * lng_radius);
loc.lat = loc.lat + (Math.sin(angle) * lat_radius);
angle += step;
}
};
답변
@Ignatius 가장 우수한 답변, MarkerClustererPlus v2.0.7에서 작동하도록 업데이트되었습니다.
-
MarkerClusterer 클래스에 프로토 타입 클릭 메소드를 다음과 같이 추가합니다. 나중에 map initialize () 함수에서이를 재정의합니다.
// BEGIN MODIFICATION (around line 715) MarkerClusterer.prototype.onClick = function() { return true; }; // END MODIFICATION
-
ClusterIcon 클래스에서 click / clusterclick 트리거 후에 다음 코드를 추가합니다.
// EXISTING CODE (around line 143) google.maps.event.trigger(mc, "click", cClusterIcon.cluster_); google.maps.event.trigger(mc, "clusterclick", cClusterIcon.cluster_); // deprecated name // BEGIN MODIFICATION var zoom = mc.getMap().getZoom(); // Trying to pull this dynamically made the more zoomed in clusters not render // when then kind of made this useless. -NNC @ BNB // var maxZoom = mc.getMaxZoom(); var maxZoom = 15; // if we have reached the maxZoom and there is more than 1 marker in this cluster // use our onClick method to popup a list of options if (zoom >= maxZoom && cClusterIcon.cluster_.markers_.length > 1) { return mc.onClick(cClusterIcon); } // END MODIFICATION
-
그런 다음지도를 초기화하고 MarkerClusterer 객체를 선언하는 initialize () 함수에서 다음을 수행합니다.
markerCluster = new MarkerClusterer(map, markers); // onClick OVERRIDE markerCluster.onClick = function(clickedClusterIcon) { return multiChoice(clickedClusterIcon.cluster_); }
multiChoice ()는 선택할 수있는 옵션 목록이있는 InfoWindow를 팝업하는 (아직 작성되지 않은) 함수입니다. markerClusterer 객체는 해당 클러스터에있는 마커 수를 확인하는 데 필요하므로 함수에 전달됩니다. 예를 들면 :
function multiChoice(clickedCluster) { if (clickedCluster.getMarkers().length > 1) { // var markers = clickedCluster.getMarkers(); // do something creative! return false; } return true; };
답변
위의 답변은 더 우아하지만 실제로 정말 믿을 수 없을 정도로 잘 작동하는 빠르고 더러운 방법을 찾았습니다. www.buildinglit.com 에서 실제로 확인할 수 있습니다.
내가 한 것은 위도와 경도에 임의의 오프셋을 내 genxml.php 페이지에 추가하여지도가 마커로 생성 될 때마다 오프셋과 함께 매번 약간 다른 결과를 반환합니다. 이것은 해킹처럼 들리지만 실제로는 마커가 겹치는 경우지도에서 클릭 할 수 있도록 임의의 방향으로 약간 이동하려면 마커 만 필요합니다. 그것은 실제로 정말 잘 작동합니다. 누가 그 복잡성을 다루고 모든 곳에서 봄을 원하기 때문에 거미 방법보다 더 잘 말할 것입니다. 마커를 선택할 수 있기를 원합니다. 무작위로 Nudging 완벽하게 작동합니다.
다음은 내 php_genxml.php에서 while 문 반복 노드 생성의 예입니다.
while ($row = @mysql_fetch_assoc($result)){ $offset = rand(0,1000)/10000000;
$offset2 = rand(0, 1000)/10000000;
$node = $dom->createElement("marker");
$newnode = $parnode->appendChild($node);
$newnode->setAttribute("name", $row['name']);
$newnode->setAttribute("address", $row['address']);
$newnode->setAttribute("lat", $row['lat'] + $offset);
$newnode->setAttribute("lng", $row['lng'] + $offset2);
$newnode->setAttribute("distance", $row['distance']);
$newnode->setAttribute("type", $row['type']);
$newnode->setAttribute("date", $row['date']);
$newnode->setAttribute("service", $row['service']);
$newnode->setAttribute("cost", $row['cost']);
$newnode->setAttribute("company", $company);
위도 및 경도 아래에 + offset이 있습니다. 위의 두 변수에서. 나는 마커를 간신히 움직일 수있을 정도로 무작위로 작은 소수를 얻기 위해 random을 0,1000으로 10000000으로 나누어야했다. 필요에 더 정확한 변수를 얻으려면 해당 변수를 자유롭게 수정하십시오.
답변
같은 건물에 여러 서비스가있는 상황에서는 실제 지점에서 반경 내에서 마커를 약간 (예 : .001도) 오프셋 할 수 있습니다. 이것은 또한 멋진 시각 효과를 생성합니다.