同一坐标中多个标记的解决方案,Google 地图混搭

发布于 2024-08-19 18:27:25 字数 117 浏览 8 评论 0 原文

我正在制作一个混搭,其中缩略图将显示在谷歌地图上。

问题是许多缩略图将共享相同的坐标。因此,如果我像标记一样绘制它们,它们将一个在另一个之上。

您是否见过针对这个问题的创造性解决方案?谢谢

I am making a mashup where thumbnails will be shown over a google map.

The problem is that many thumbnails will share the same coordinate. So if I plot them like markers, they will be one on top of the other.

Have you seen any creative solution for this problem? Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

不再见 2024-08-26 18:27:26

有一些 Javascript 库可以实现集群,并且很容易集成到现有的混搭中:

  • MarkerClusterer - 我使用这是一个混搭,发现它很容易集成,有一组很好的默认图标。
  • ClusterMarker - 我没用过这个,但看起来很漂亮功能性的。

您还可以阅读这篇博文 概述了各种替代方案。

There are a few Javascript libraries that implement Clustering and are very easy to integrate into an existing mashup:

  • MarkerClusterer - I used this for a mashup and found it easy to integrate, with a nice set of default icons.
  • ClusterMarker - I haven't used this one, but it seems pretty functional.

You can also read this blog post which goes over the various alternatives.

梦醒灬来后我 2024-08-26 18:27:26

您需要查找术语“聚类”。您基本上只显示一个标记,表明该位置实际上有多个标记。然后,在适当的缩放级别,标记开始单独显示。

如果它们位于完全相同的坐标并且永远不会发散,那么您将需要实现当您将鼠标悬停在聚集标记上时在屏幕上弹出的内容(例如包含缩略图列表的浮动 DIV,供用户查看)选择/查看,甚至是上下文菜单,他们可以右键单击群集并选择单个项目)

You'll want to look up the term Clustering. You basically just show one marker that indicates there are actually more than one marker at that location. Then at an appropriate zoom level the markers start to appear separately.

If they are at the exact same coordinates and will never diverge, then you will need to implement something that pops-up on the screen when you hover over the clustered marker (like a floating DIV that contains a list of the thumbnails for the person to select/view, or even a context menu where they can right click the cluster and select an individual item)

明媚如初 2024-08-26 18:27:26

使用聚类。将一组标记作为簇。一个簇将在内部呈现许多标记。

Use clustering .make group of markers as cluster.one cluster will present many markers inside.

So尛奶瓶 2024-08-26 18:27:26

我有一个优雅而美丽的解决方案:

@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

I've got an elegant and beautiful solution:

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

Full code of Fragment:
https://github.com/master255/MapFragment

还在原地等你 2024-08-26 18:27:25

聚类当然很有用,但它并没有解决最初的问题——如果标记共享相同的精确坐标,则如何显示标记。 Google Maps API v3 根本不这样做。它只显示其中之一。

@RedBlueThing 建议的集群解决方案不能解决这个问题。

有几个选择。 @Bryan 建议 - 手动进行一些预处理,并将描述性信息放入最后一个标记的信息窗口中。

或者 - 我更喜欢 - 是对标记进行预处理,以稍微(10m 左右)改变共享相同确切位置的标记的坐标。如果您有能力放弃这种精度水平。请在此处查看此类解决方案 http:// techxplorer.com/2010/02/05/managing-markers-with-the-same-coordinates-in-a-google-map/。我进一步修改了代码 - 请参阅此处 https://gist.github.com/873142

Clustering is certainly useful, but it doesn't address the original question - which is how to display markers if they share the same exact coordinates. Google Maps API v3 simply doesn't do that. It just displays one of them.

Clustering solutions suggested by @RedBlueThing do not address this.

There are a couple of options. One was suggested by @Bryan - to do some pre-processing manually, and put descriptive information in the info window for the last marker.

Alternatively - which I prefer - is to pre-process the markers to just ever so slightly (10m or so) alter the coordinates of those that share the same exact location. If you can afford to give up that kind of level of precision. See one such solution here http://techxplorer.com/2010/02/05/managing-markers-with-the-same-coordinates-in-a-google-map/. I have further modified the code - see here https://gist.github.com/873142.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文