如何居中/设置地图缩放以覆盖 Xamarin.Forms 上可见的所有标记?

Posted

技术标签:

【中文标题】如何居中/设置地图缩放以覆盖 Xamarin.Forms 上可见的所有标记?【英文标题】:How to Center/Set Zoom of Map to cover all markers visible on Xamarin.Forms? 【发布时间】:2015-09-23 17:28:04 【问题描述】:

我正在为我的地图设置多个标记

我可以静态设置缩放级别和中心

但我想要的是以所有标记为中心并缩放级别以填充所有可见标记

我可以使用接收 MapSpan 的 Gmaps.MoveToRegion 方法。问题是,我不知道如何计算显示所有标记所需的 MapSpan。

我正在使用 Xamarin.Forms.Maps 和 Xam.Plugin.MapExtend.Abstractions

提前致谢!

【问题讨论】:

有一个名为 map.fitBounds() 的函数可以执行您为 javascript API 和 android API 描述的功能。这是一个link 进一步解释。不确定您将如何在 Xamarin 中执行此操作,但希望这是一个好的开始。 【参考方案1】:

首先您需要将自定义地图渲染添加到将继承 MapRenderer、GoogleMap.IInfoWindowAdapter 的 android 项目中

    public class MyMapRenderer : MapRenderer, GoogleMap.IInfoWindowAdapter

我添加了 2 个私有字段

    private GoogleMap _map;
    private LatLngBounds.Builder _builder;

在构造函数中初始化你的_builder:

    public MyMapRenderer(Context context) : base(context)
    
        _builder = new LatLngBounds.Builder();
    

当覆盖 OnMapReady 方法时,将 GoogleMap 属性设置为:

    protected override void OnMapReady(GoogleMap map)
    
        base.OnMapReady(map);

        NativeMap.InfoWindowClick += OnInfoWindowClick;
        NativeMap.SetInfoWindowAdapter(this);
        if (_map == null)
        
            _map = map;
        
    

您需要重写 CreateMarker 方法,以便更改缩放级别

    protected override MarkerOptions CreateMarker(Pin pin)
    
        var p = (THHPin)pin;

        var marker = new MarkerOptions();
        LatLng position = new LatLng(pin.Position.Latitude, pin.Position.Longitude);
        marker.SetPosition(position);
        marker.SetTitle(pin.Label);
        marker.SetSnippet(pin.Address);

        _builder.Include(position);
        LatLngBounds bounds = _builder.Build();

        CameraUpdate cu = CameraUpdateFactory.NewLatLngBounds(bounds, 20);

        _map.MoveCamera(cu);
        return marker;
    

【讨论】:

这适用于 ios 和 Android? @Ljupcho Hristov @KalleP 是的,这是在共享项目中【参考方案2】:

我使用在这里找到的算法解决了这个该死的问题:http://www.movable-type.co.uk/scripts/latlong.html

在 Xamarin 中是这样的:

var radioTierra = 6371000; //metros
        var latitud1Radianes = pos1.Latitude * (Math.PI / 180.0);
        var latitud2Radianes = pos2.Latitude * (Math.PI / 180.0);
        var longitud1Radianes = pos1.Longitude * (Math.PI / 180.0);

        var deltaLatitud = (pos2.Latitude - pos1.Latitude) * (Math.PI / 180.0);
        var deltaLongitud = (pos2.Longitude - pos1.Longitude) * (Math.PI / 180.0);


        var sumando1 = Math.Sin(deltaLatitud / 2) * Math.Sin(deltaLatitud / 2);
        var sumando2 = Math.Cos(latitud1Radianes) * Math.Cos(latitud2Radianes) * Math.Sin(deltaLongitud / 2) * Math.Sin(deltaLongitud / 2);
        List<double> sumandos = new List<double>();
        sumandos.Add(sumando1);
        sumandos.Add(sumando2);
        var a = sumandos.Sum();
        var c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));

        var distance = radioTierra * c;

        /* Δφ es deltaLatitud
         * Δλ es deltaLongitud*/
        var Bx = Math.Cos(latitud2Radianes) * Math.Cos(deltaLongitud);
        var By = Math.Cos(latitud2Radianes) * Math.Sin(deltaLongitud);
        var φ3 = Math.Atan2(Math.Sin(latitud1Radianes) + Math.Sin(latitud2Radianes),
                            Math.Sqrt((Math.Cos(latitud1Radianes) + Bx) * (Math.Cos(latitud2Radianes) + Bx) + By * By));//Latitud del punto medio
        var λ3 = longitud1Radianes + Math.Atan2(By, Math.Cos(longitud1Radianes) + Bx);//Longitud del punto medio

        var centro = new Xamarin.Forms.Maps.Position(φ3, λ3);
        Distance distancia = new Xamarin.Forms.Maps.Distance(distance + 0.2);

        Gmaps.MoveToRegion(MapSpan.FromCenterAndRadius(centro, distancia));

【讨论】:

嗨,我知道这是一篇旧帖子,但你能解释一下你的代码吗? :// @Emixam23 这里解释一下:movable-type.co.uk/scripts/latlong.html @AbelAlejandro 能否请您解释一下当标记数超过 2 时,上述计算将如何变化。比如说 4 个标记。 Lat1, Long1 将是 4 个标记的最小纬度和经度.. Lat2, Long2 是最大纬度和经度吗? @Vicky 这并不意味着超过 2 个标记。如果我必须这样做以支持 N 个标记,我会选择纬度和经度的绝对最大值和最小值,因为所有标记都适合这 4 个值。 @AbelAlejandro 谢谢.. 我正在尝试按照您的建议使用最大和最小纬度和经度使其工作.. 将更新它的进展情况..【参考方案3】:

我在下面的 c# 代码中取得了成功。只需将每个标记的位置记录为 LatLng 对象即可。

locationManager = (LocationManager)GetSystemService(Context.LocationService);

Criteria criteria = new Criteria();

criteria.Accuracy = Accuracy.Fine;
criteria.PowerRequirement = Power.Low;

provider = locationManager.GetBestProvider(criteria, true);

location = locationManager.GetLastKnownLocation(provider);

marker1lat = location.Latitude;
marker1lng = location.Longitude;

marker2lat = location.Latitude;
marker2lng = location.Longitude;

LatLng marker1LatLng = new LatLng(marker1lat, marker1lng);
Latlng marker2LatLng = new LatLng(marker2lat, marker2lng);

LatLngBounds.Builder b = new LatLngBounds.Builder()
                    .Include(marker1LatLng)
                    .Include(marker2LatLng);

mMap.MoveCamera(CameraUpdateFactory.NewLatLngBounds(b.Build(), 120));

【讨论】:

以上是关于如何居中/设置地图缩放以覆盖 Xamarin.Forms 上可见的所有标记?的主要内容,如果未能解决你的问题,请参考以下文章

保持地图居中无论你在哪里捏缩放安卓

新手中心/设置地图缩放以覆盖所有可见标记? [复制]

如何使用 OpenLayers 显示、居中和缩放地图?

单击多边形,然后缩放和居中地图

如何设置谷歌地图缩放级别以显示所有标记?

有没有办法在 AGM 地图中设置边界和缩放级别?