2010-01-27 13 views
10

Tworzę łącznik, w którym miniatury będą wyświetlane na mapie google.Rozwiązania dla wielu znaczników o tej samej współrzędnej, Mashup Google Map

Problem polega na tym, że wiele miniaturek ma tę samą współrzędną. Więc jeśli je wykreślę jak markery, będą one jedna na drugiej.

Czy widziałeś jakieś twórcze rozwiązanie tego problemu? Dzięki

+0

spróbować zmniejszyć ich rozmiar? Zezwalaj na rozwijanie selektora w przypadku wielu w jednym miejscu? Są to tylko domysły, nie wiem nic o API. –

Odpowiedz

3

Istnieje kilka bibliotek JavaScript, które implementują klastrowanie i są bardzo łatwe do zintegrowania z istniejącym mashup:

  • MarkerClusterer - I used to dla mashup i znalazłem to ea sy do integracji, z ładnym zestawem domyślnych ikon.
  • ClusterMarker - Nie użyłem tego, ale wydaje się całkiem funkcjonalne.

Możesz również przeczytać tę blog post, która zawiera różne alternatywy.

3

Będziesz chciał sprawdzić termin Klasterowanie. Po prostu pokazujesz jeden znacznik, który wskazuje, że w danym miejscu znajduje się więcej niż jeden znacznik. Następnie przy odpowiednim poziomie powiększenia znaczniki zaczynają pojawiać się osobno.

Jeśli mają one dokładnie takie same współrzędne i nigdy się nie rozejdą, to będziesz musiał zaimplementować coś, co pojawi się na ekranie po najechaniu kursorem na znacznik klastrowy (jak pływający DIV, który zawiera listę miniaturek aby osoba mogła wybrać/wyświetlić, a nawet menu kontekstowe, w którym można kliknąć prawym przyciskiem myszy na klaster i wybrać pojedynczy element)

+0

dzięki Bryan bardzo przydatne – Victor

9

Tworzenie klastrów jest z pewnością przydatne, ale nie odnosi się do pierwotnego pytania - w jaki sposób wyświetlać znaczniki, jeśli mają one te same dokładne współrzędne. Google Maps API v3 po prostu tego nie robi. Po prostu wyświetla jeden z nich.

Rozwiązania klastrowania zasugerowane przez @RedBlueThing nie rozwiązują tego problemu.

Istnieje kilka opcji. Jedna została zasugerowana przez @Bryan - aby ręcznie przeprowadzić wstępne przetwarzanie i umieścić opisowe informacje w oknie informacyjnym dla ostatniego znacznika.

Alternatywnie - co preferuję - to wstępne przetwarzanie znaczników do tak nieznacznego (10 m) zmiany współrzędnych tych, które mają tę samą dokładną lokalizację. Jeśli możesz sobie pozwolić na rezygnację z tego poziomu precyzji. Zobacz jedno takie rozwiązanie tutaj http://techxplorer.com/2010/02/05/managing-markers-with-the-same-coordinates-in-a-google-map/. Następnie zmodyfikowałem kod - patrz tutaj: https://gist.github.com/873142.

+0

Twoja "alternatywa" to sprytne i proste rozwiązanie. Wprowadziłem to z losowym "przesunięciem" około 1 metra na każdym markerze, co wystarczy, aby oddzielić znaczniki podczas powiększania. –

0

Użyj klastrowania .wybierz grupę znaczników jako klastra cluster.one zaprezentuje wiele znaczników wewnątrz.

0

Mam eleganckie i piękne rozwiązanie:

@Override 
public boolean onClusterClick(Cluster<ProfileCardDTO> cluster) 
{ 
    if (inProcessOfClick.size() > 0) 
    { 
     changeRenderMarkerType(doctorMarkerRenderer.getMarkerType()); 
     for (Polyline line : polylines) 
     { 
      line.remove(); 
     } 
     polylines.clear(); 
    } 
    boolean same = true; 
    ProfileCardDTO tmpProfile = null; 
    for (ProfileCardDTO profile : cluster.getItems()) 
    { 
     if (tmpProfile != null) 
     { 
      if ((Math.abs(Float.parseFloat(tmpProfile.getPractice().getLatitude()) - Float 
        .parseFloat(profile 
          .getPractice() 
          .getLatitude())) > 0.00001f) || (Math.abs(Float.parseFloat(tmpProfile 
        .getPractice().getLongitude()) - Float.parseFloat(profile 
        .getPractice() 
        .getLongitude())) > 0.00001f)) 
      { 
       same = false; 
       break; 
      } 
     } 
     tmpProfile = profile; 
    } 
    if (zoomLevel >= 12 && same) 
    { 
     inProcessOfClick.clear(); 
     int count = cluster.getSize(); 
     double a = 360.0/count; 
     double radius = 0.0006; 
     if (zoomLevel < 17.7) 
     { 
      radius = 0.0005; 
     } else if (zoomLevel < 18.7) 
     { 
      radius = 0.0003; 
     } else if (zoomLevel < 19.7) 
     { 
      radius = 0.00015; 
     } else if (zoomLevel <= 20.7) 
     { 
      radius = 0.00007; 
     } else if (zoomLevel > 20.7) 
     { 
      radius = 0.00005; 
     } 
     int i = 0; 
     final long duration = 500; 
     final long start = SystemClock.uptimeMillis(); 
     final Interpolator interpolator = new LinearInterpolator(); 
     for (ProfileCardDTO profile : cluster.getItems()) 
     { 
      MarkerOptions mrk = new MarkerOptions(); 
      double x = radius * Math.cos((a * i)/180 * Math.PI); 
      double y = radius * Math.sin((a * i)/180 * Math.PI); 
      LatLng latLngEnd = new LatLng(profile.getPosition().latitude + x, profile 
        .getPosition().longitude + y); 
      LatLng latLngStart = profile.getPosition(); 
      mrk.position(latLngStart); 
      doctorMarkerRenderer.onBeforeClusterItemRendered(profile, mrk); 
      Marker tmpMrk = clusterManager.getMarkerCollection().addMarker(mrk); 
      Handler handler = new Handler(); 
      handler.post(new Runnable() 
      { 
       @Override 
       public void run() 
       { 
        long elapsed = SystemClock.uptimeMillis() - start; 
        if (elapsed > duration) 
         elapsed = duration; 
        float t = interpolator.getInterpolation((float) elapsed/duration); 
        double lng = t * latLngEnd.longitude + (1 - t) * latLngStart.longitude; 
        double lat = t * latLngEnd.latitude + (1 - t) * latLngStart.latitude; 
        tmpMrk.setPosition(new LatLng(lat, lng)); 
        if (t < 1.0) 
        { 
         handler.postDelayed(this, 10); 
        } else 
        { 
         PolylineOptions line = 
           new PolylineOptions().add(cluster.getPosition(), 
             cluster.getPosition(), 
             latLngEnd, 
             latLngEnd) 
             .width(5).color(Color.BLACK); 
         polylines.add(getGoogleMap().addPolyline(line)); 
        } 
       } 
      }); 
      doctorMarkerRenderer.getmMarkerCache().put(profile, tmpMrk); 
      clusterManager.addItem(profile); 
      inProcessOfClick.add(profile); 
      i++; 
     } 
     tmpCluster = cluster; 
     bringMarkerToTop(selectedDoctorMiniProfile); 
     new Handler().postDelayed(() -> 
     { 
      if (doctorMarkerRenderer.getMarker(cluster) != null) 
       doctorMarkerRenderer.getMarker(cluster).setAlpha(0.5f); 
     }, 250); 
    } else 
    { 
     LatLngBounds.Builder builder = new LatLngBounds.Builder(); 
     for (ProfileCardDTO profile : cluster.getItems()) 
     { 
      Practice2 location = profile.getLocation(); 
      LatLng latLng = new LatLng(Double.parseDouble(location.getLatitude()), Double.parseDouble(location 
        .getLongitude())); 
      builder.include(latLng); 
     } 
     LatLngBounds latLngBounds = builder.build(); 
     CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngBounds(latLngBounds, getResources().getDimensionPixelSize(R.dimen.map_padding)); 
     getGoogleMap().animateCamera(cameraUpdate, ANIMATE_DURATION_MS, new GoogleMap.CancelableCallback() 
     { 
      @Override 
      public void onFinish() 
      { 
       changeRenderMarkerType(doctorMarkerRenderer.getMarkerType()); 
      } 

      @Override 
      public void onCancel() 
      { 
      } 
     }); 
    } 
    return true; 
} 

pełny kod Fragment: https://github.com/master255/MapFragment