Решения для многих маркеров в одной и той же координате, mashup Google Map
Я делаю mashup, где миниатюры будут показаны на карте google.
Проблема заключается в том, что многие миниатюры будут иметь одну и ту же координату. Поэтому, если я нарисую их как маркеры, они будут один поверх другого.
Вы видели какое-либо творческое решение этой проблемы? Благодаря
Ответы
Ответ 1
Существует несколько библиотек Javascript, которые реализуют Clustering и очень легко интегрируются в существующий mashup:
- MarkerClusterer - я used this для mashup и легко интегрируется, с хорошим набором значков по умолчанию.
- ClusterMarker - я не использовал этот, но он кажется довольно функциональным.
Вы также можете прочитать этот пост в блоге, который охватывает различные альтернативы.
Ответ 2
Кластеризация, безусловно, полезна, но она не затрагивает первоначальный вопрос - как отображать маркеры, если они имеют одни и те же точные координаты. API Google Maps v3 просто не делает этого. Он просто отображает один из них.
Решения кластеризации, предлагаемые @RedBlueThing, не решают этого.
Есть несколько вариантов. Один из них предложил @Bryan - выполнить некоторую предварительную обработку вручную и поместить описательную информацию в информационное окно для последнего маркера.
В качестве альтернативы - что я предпочитаю - это предварительно обработать маркеры так просто (10 м или около того) изменить координаты тех, которые имеют одинаковое точное местоположение. Если вы можете позволить себе отказаться от такого уровня точности. См. Одно из таких решений здесь http://techxplorer.com/2010/02/05/managing-markers-with-the-same-coordinates-in-a-google-map/. Я также изменил код - см. Здесь https://gist.github.com/873142.
Ответ 3
Вы хотите найти термин "Кластеризация". В основном вы просто показываете один маркер, который указывает, что на этом месте имеется более одного маркера. Затем при соответствующем уровне масштабирования маркеры начинают появляться отдельно.
Если они находятся в одинаковых координатах и никогда не расходятся, вам нужно будет реализовать что-то, что появляется на экране, когда вы наводите курсор на кластерный маркер (например, плавающий DIV, содержащий список миниатюр для человека для выбора/просмотра или даже контекстного меню, где они могут щелкнуть правой кнопкой мыши кластер и выбрать отдельный элемент)
Ответ 4
Использовать кластеризацию .make группа маркеров в кластере cluster.one представит много маркеров внутри.
Ответ 5
У меня есть элегантное и красивое решение:
@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;
}
Полный код фрагмента:
https://github.com/master255/MapFragment