2010-01-27 21 views
10

Estoy haciendo un mashup donde las miniaturas se mostrarán en un mapa de Google.Soluciones para muchos marcadores en la misma coordenada, Google Map mashup

El problema es que muchas miniaturas compartirán la misma coordenada. Entonces, si los trazo como marcadores, serán uno encima del otro.

¿Has visto alguna solución creativa para este problema? Gracias

+0

tratar de reducir su tamaño? Permitir un selector desplegable en el caso de muchos en un solo lugar? Estas son solo conjeturas, no sé nada sobre la API. –

Respuesta

3

Existen algunas bibliotecas de Javascript que implementan Clustering y son muy fáciles de integrar en un mashup existente:

  • MarkerClusterer - me used esto por un mashup y lo encontró ea sy para integrar, con un bonito conjunto de iconos predeterminados.
  • ClusterMarker - No he usado este, pero parece bastante funcional.

También puede leer este blog post que repasa las diversas alternativas.

3

Querrá consultar el término Clustering. Básicamente, solo muestra un marcador que indica que en realidad hay más de un marcador en esa ubicación. Luego, a un nivel de zoom apropiado, los marcadores comienzan a aparecer por separado.

Si están exactamente en las mismas coordenadas y nunca divergirán, tendrá que implementar algo que aparezca en la pantalla cuando pase el puntero sobre el marcador agrupado (como un DIV flotante que contiene una lista de las miniaturas para que la persona seleccione/vea, o incluso un menú contextual donde pueden hacer clic con el botón derecho en el clúster y seleccionar un elemento individual)

+0

gracias Bryan muy útil – Victor

9

La agrupación en clústeres es ciertamente útil, pero no aborda la pregunta original, que es cómo mostrar marcadores si comparten las mismas coordenadas exactas. Google Maps API v3 simplemente no hace eso. Simplemente muestra uno de ellos.

Las soluciones de agrupamiento sugeridas por @RedBlueThing no abordan esto.

Hay un par de opciones. Uno fue sugerido por @Bryan - para hacer un preprocesamiento manual, y poner información descriptiva en la ventana de información para el último marcador.

Alternativamente, lo que prefiero, es preprocesar los marcadores ligeramente (10 m más o menos) alterando las coordenadas de aquellos que comparten la misma ubicación exacta. Si puedes permitirte abandonar ese tipo de nivel de precisión. Vea una de esas soluciones aquí http://techxplorer.com/2010/02/05/managing-markers-with-the-same-coordinates-in-a-google-map/. Modifiqué el código - vea aquí https://gist.github.com/873142.

+0

Su "alternativa" es una solución inteligente y simple. Lo he implementado con un "desplazamiento" aleatorio de aproximadamente 1 metro aproximadamente en cada marcador, que es suficiente para separar los marcadores cuando se acerca el zoom. –

0

Usar la agrupación en clúster. Hacer que un grupo de marcadores como clúster.Un clúster presente muchos marcadores dentro.

0

Tengo una solución elegante y hermoso:

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

código completo del Fragmento: https://github.com/master255/MapFragment

Cuestiones relacionadas