[Javascript] خرائط جوجل API V3 - علامات متعددة في نفس المكان بالضبط


Answers

لا يعد إزاحة العلامات حلاً حقيقياً إذا كانت موجودة في نفس المبنى. ما تريد فعله هو تعديل markerclusterer.js مثل:

  1. إضافة طريقة النقر النموذج الأولي في فئة MarkerClusterer ، مثل ذلك - سنقوم بتجاوز هذا في وقت لاحق في وظيفة تهيئة () الخريطة:

    MarkerClusterer.prototype.onClick = function() { 
        return true; 
    };
    
  2. في فئة 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);
    }
    
  3. ثم ، في الدالة initialize () حيث تقوم بتهيئة الخريطة وتعلن عن كائن MarkerClusterer:

    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;
    }
    
Question

بت تمسك على هذا واحد. أنا استرجاع قائمة السياقات الجغرافية عبر JSON وفروها على خريطة جوجل. كل شيء يعمل بشكل جيد ما عدا في المثال عندما يكون لدي علامتين أو أكثر في نفس المكان بالضبط. تعرض واجهة برمجة التطبيقات فقط علامة 1 - العلامة الأعلى. هذا عادل بما فيه الكفاية أفترض ولكن تود أن تجد طريقة لعرض كل منهم بطريقة أو بأخرى.

لقد بحثت في Google ووجدت بعض الحلول ولكن يبدو أنها غالبًا لـ V2 من واجهة برمجة التطبيقات أو أنها ليست رائعة. من الناحية المثالية ، أرغب في الحصول على حل حيث تنقر على نوع ما من علامة المجموعة ويظهر بعد ذلك العلامات التي تتجمع حول المكان الذي توجد فيه.

أي شخص لديه هذه المشكلة أو ما شابه ، وسوف تهتم لمشاركة الحل؟




تحقق من Marker Clusterer لـ V3 - تجمع هذه المكتبة النقاط القريبة في علامة مجموعة. يتم تكبير الخريطة عند النقر على المجموعات. كنت أتخيل عند التكبير في حق كنت لا تزال تواجه نفس المشكلة مع علامات على نفس المكان على الرغم من.




هذا أكثر من حل "سريع وقذر" مؤقت مماثل لما يقترحه ماثيو فوكس ، هذه المرة باستخدام جافا سكريبت.

في جافا سكريبت ، يمكنك فقط تعويض خطوط العرض وطول جميع مواقعك بإضافة تخالف عشوائي صغير لكل منهما على سبيل المثال

myLocation[i].Latitude+ = (Math.random() / 25000)

(وجدت أن التقسيم بمقدار 25000 يعطي فصلًا كافيًا ولكن لا يتحرك بشكل ملحوظ من الموقع المحدد مثل عنوان محدد)

وهذا يجعل العمل الجيد بشكل معقول من تعويضهم عن بعضهم البعض ، ولكن فقط بعد أن قمت بتصغير عن كثب. عند التصغير ، لن يكون من الواضح أن هناك خيارات متعددة للموقع.




أنا أحب الحلول البسيطة لذلك هنا الألغام. بدلا من تعديل lib ، مما يجعل من الصعب على mantain. يمكنك ببساطة مشاهدة الحدث من هذا القبيل

google.maps.event.addListener(mc, "clusterclick", onClusterClick);

ثم يمكنك إدارتها

function onClusterClick(cluster){
    var ms = cluster.getMarkers();

أنا ، أي استخدام bootstrap لإظهار لوحة مع قائمة. التي أجدها أكثر راحة وقابلية للاستخدام من أماكن spiderfying على "مزدحمة". (إذا كنت تستخدم احتمالات clusterer هل سينتهي بك المطاف بتصادمات بمجرد spiderfy). يمكنك التحقق من التكبير هناك أيضا.

راجع للشغل. أنا فقط وجدت النشرة ويبدو أنها تعمل بشكل أفضل بكثير ، وعملية spiderfy يعمل بشكل جيد جدا http://leaflet.github.io/Leaflet.markercluster/example/marker-clustering-realworld.10000.html وهو مفتوح المصدر.




بالتوسع في الإجابات المذكورة أعلاه ، فقط تأكد من تعيين خيار maxZoom عند تهيئة كائن الخريطة.




توسيع الإجابات أعلاه ، عندما تكون قد حصلت على سلاسل مرفقة ، ولم تتم إضافة / طرح (على سبيل المثال "37.12340-0.00069") ، قم بتحويل خط الطول / العرض الأصلي إلى floats ، على سبيل المثال باستخدام parseFloat () ، ثم قم بإضافة التصحيحات أو طرحها.




لقد استخدمت هذا بجانب 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);



بالنسبة للحالات التي توجد فيها خدمات متعددة في نفس المبنى ، يمكنك تعويض العلامات قليلاً فقط (على سبيل المثال .001 درجة) ، في نصف قطر من النقطة الفعلية. يجب أن ينتج هذا أيضًا تأثيرًا مرئيًا رائعًا.