4

iOS用のgoogle maps sdkでRegionを設定するには? マーカーの位置と半径のズームを設定したい。

4

9 に答える 9

16

アップデート:

以下の元の回答は、SDKのバージョン1.2で廃止されました。これで、クラスのfitBounds:メソッドを使用できるようになります。GMSCameraUpdate

https://developers.google.com/maps/documentation/ios/reference/interface_g_m_s_camera_update


元の答え:

MKMapPointMapKitのタイプは、マップの2D投影を定義します。投影の実際の値は不透明であることが意図されていますが、ズームレベル20のピクセルと同等であることがわかります。これを使用して、緯度/経度の値をピクセル、つまりスケール、つまりズームレベルに変換できます。

表示する領域の境界を指定する2つの場所を定義することから始めます。これらは、バウンディングボックスの反対側の角、または2つの場所だけである可能性があります。たとえば、次のようになります。

CLLocationCoordinate2D location1 = 
    CLLocationCoordinate2DMake(-33.8683, 151.2086); // Sydney
CLLocationCoordinate2D location2 = 
    CLLocationCoordinate2DMake(-31.9554, 115.8585); // Perth

含めたいポイントが3つ以上ある場合は、それらの境界を自分で計算できます。GMSCoordinateBoundsこれは、たとえば次を使用して実行することもできます。

GMSCoordinateBounds* bounds =
    [[GMSCoordinateBounds alloc]
    initWithCoordinate: CLLocationCoordinate2DMake(-33.8683, 151.2086) // Sydney
    andCoordinate: CLLocationCoordinate2DMake(-31.9554, 115.8585)]; // Perth
bounds = [bounds including: 
    CLLocationCoordinate2DMake(-12.4667, 130.8333)]; // Darwin
CLLocationCoordinate2D location1 = bounds.southWest;
CLLocationCoordinate2D location2 = bounds.northEast;

次に、マップビューのサイズをポイントで取得する必要があります。あなたはこれを使うことができます:

float mapViewWidth = _mapView.frame.size.width;
float mapViewHeight = _mapView.frame.size.height;

ただし、これは、マップビューを既に作成している場合にのみ機能します。また、スタートガイドのサンプルコードを使用している場合は、フレームがに設定されCGRectZeroます。これは、実際のサイズが後で画面いっぱいに設定されるためです。このような場合、全画面マップを作成している場合は、次のようなものが必要になる場合があります。

float mapViewWidth = [UIScreen mainScreen].applicationFrame.size.width;
float mapViewHeight = [UIScreen mainScreen].applicationFrame.size.height;

それ以外の場合は、マップビューを作成するときに使用するサイズを使用します。

これで、カメラの位置を計算するために必要な情報が得られました。

MKMapPoint point1 = MKMapPointForCoordinate(location1);
MKMapPoint point2 = MKMapPointForCoordinate(location2);

MKMapPoint centrePoint = MKMapPointMake(
    (point1.x + point2.x) / 2,
    (point1.y + point2.y) / 2);
CLLocationCoordinate2D centreLocation = MKCoordinateForMapPoint(centrePoint);

double mapScaleWidth = mapViewWidth / fabs(point2.x - point1.x);
double mapScaleHeight = mapViewHeight / fabs(point2.y - point1.y);
double mapScale = MIN(mapScaleWidth, mapScaleHeight);

double zoomLevel = 20 + log2(mapScale);

GMSCameraPosition *camera = [GMSCameraPosition
    cameraWithLatitude: centreLocation.latitude
    longitude: centreLocation.longitude
    zoom: zoomLevel];

次に、このカメラでマップビューを初期化するか、マップビューをこのカメラに設定できます。

このコードをコンパイルするには、MapKitフレームワークをプロジェクトに追加してから、インポートする必要があります。

#import <MapKit/MapKit.h>

座標が日付変更線にまたがる場合、このコードはラップアラウンドを処理しないことに注意してください。たとえば、このコードを東京とハワイで使用しようとすると、太平洋の領域を表示する代わりに、ほぼ全世界を表示しようとします。ポートレートモードでは、左側にハワイ、右側に東京が表示されるほどズームアウトできないため、地図はアフリカを中心に配置され、どちらの場所も表示されません。必要に応じて、日付変更線でのラップアラウンドを処理するように上記のコードを変更できます。

于 2013-02-25T17:58:36.800 に答える
2

私は現在この方法を使用しています。

self.markers は場所 ID によって格納されたマーカーを持つ辞書であり、self.currentLocation は CLLocation2D であり、self.mapView は GMSMapView です。

ここでの計算は、幅または高さのサイズを一致させるかどうかのチェックであり、x1 / pow(2, zoom1) = x2 / pow(2, zoom2)", zoom2 = log2(x2 * pow(2, self.mapView.camera.zoom) / x1) になります。

- (void)fitMarkers
{
    if (2 > self.markers.count)
    {
        [self.mapView animateToCameraPosition:[GMSCameraPosition cameraWithTarget:self.currentLocation.coordinate zoom:kZoom]];

        return;
    }

    NSArray* markers = self.markers.allValues;

    GMSCoordinateBounds* markerBounds = [[GMSCoordinateBounds alloc] initWithCoordinate:((id<GMSMarker>)markers[0]).position andCoordinate:((id<GMSMarker>)markers[1]).position];

    for (id<GMSMarker> marker in markers)
    {
        markerBounds = [markerBounds including:marker.position];
    }

    // get marker bounds in points
    CGPoint markerBoundsTopLeft = [self.mapView.projection pointForCoordinate:CLLocationCoordinate2DMake(markerBounds.northEast.latitude, markerBounds.southWest.longitude)];
    CGPoint markerBoundsBottomRight = [self.mapView.projection pointForCoordinate:CLLocationCoordinate2DMake(markerBounds.southWest.latitude, markerBounds.northEast.longitude)];

    // get user location in points
    CGPoint currentLocation = [self.mapView.projection pointForCoordinate:self.currentLocation.coordinate];

    CGPoint markerBoundsCurrentLocationMaxDelta = CGPointMake(MAX(fabs(currentLocation.x - markerBoundsTopLeft.x), fabs(currentLocation.x - markerBoundsBottomRight.x)), MAX(fabs(currentLocation.y - markerBoundsTopLeft.y), fabs(currentLocation.y - markerBoundsBottomRight.y)));

    // the marker bounds centered on self.currentLocation
    CGSize centeredMarkerBoundsSize = CGSizeMake(2.0 * markerBoundsCurrentLocationMaxDelta.x, 2.0 * markerBoundsCurrentLocationMaxDelta.y);

    // inset the view bounds to fit markers
    CGSize insetViewBoundsSize = CGSizeMake(self.mapView.bounds.size.width - kMarkerSize / 2.0 - kMarkerMargin, self.mapView.bounds.size.height - kMarkerSize / 2.0 - kMarkerSize);

    CGFloat x1;
    CGFloat x2;

    // decide which axis to calculate the zoom level with by comparing the width/height ratios
    if (centeredMarkerBoundsSize.width / centeredMarkerBoundsSize.height > insetViewBoundsSize.width / insetViewBoundsSize.height)
    {
        x1 = centeredMarkerBoundsSize.width;
        x2 = insetViewBoundsSize.width;
    }
    else
    {
        x1 = centeredMarkerBoundsSize.height;
        x2 = insetViewBoundsSize.height;
    }

    CGFloat zoom = log2(x2 * pow(2, self.mapView.camera.zoom) / x1);

    GMSCameraPosition* camera = [GMSCameraPosition cameraWithTarget:self.currentLocation.coordinate zoom:zoom];

    [self.mapView animateToCameraPosition:camera];
}
于 2013-04-14T15:21:57.097 に答える
0

フレームワークのヘッダーファイルを検索したところ、次のコードに使用できるインターフェイスのみが見つかりました。これは開始点となる可能性があります。ここでの問題は、他のヘッダーの1つにGMSCoordinateBoundsのインポートが見つからないため、GMSMapViewでこの領域を表示する方法が見つからないことです。

GMSVisibleRegion region;
region.farLeft = CLLocationCoordinate2DMake(farLeftLatitude, farLeftlongitude);
region.farRight = CLLocationCoordinate2DMake(farRightlatitude, farRightlongitude); 

GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithRegion:region];
于 2013-02-24T23:21:01.987 に答える
0

2014 年 6 月現在、この回答は、指定されたマーカーの配列を反復処理し、それに応じて境界を設定する最も簡単な方法です。

于 2014-06-13T17:03:45.270 に答える