相机和视图

请选择平台: Android iOS JavaScript

借助 Maps SDK for iOS,您可以通过更改地图的摄像头来更改用户查看地图的视角。

借助 Maps SDK for iOS,用户可以倾斜和旋转地图,将其调整为适合其情境的方向。在任何缩放级别下,用户都可以平移地图或更改其视角,而只会发生很小的延迟。

对摄像头所做的更改不会使标记、多段线或您添加的其他图形发生变化,但您可能需要更改所添加的内容,使其更适合新视图。

地图的视图

Maps SDK for iOS 使用墨卡托投影法在设备屏幕(平面)上呈现地球的表面(球面)。

相机位置

地图视图被建模成一个俯视某个平面的镜头。下列属性指定了镜头的位置(也进而决定了地图的渲染效果):目标(纬度/经度位置)方向角倾斜度缩放级别

镜头属性图

目标(位置)

镜头目标是地图中心的位置,以纬度和经度坐标形式指定。

纬度可以介于 -85 度(含)和 85 度(含)之间。不在此范围内的值会被调整为此范围内最接近的值。例如,如果将纬度指定为 100,系统会将该值设为 85。经度范围为 -180 度(含)到 180 度(含)。不在此范围内的值会被换算为 (-180, 180) 范围内的值。例如,480、840 和 1200 都会换算为 120 度。

方向角(方向)

镜头方向角指定了罗盘方向,以相对于正北方(对应于地图的顶部边缘)的角度来表示。从地图中心到顶部边缘画一条垂直线,镜头朝向相对于正北方的角度(以度为单位)即为方向角。

方向角为 0 表示地图顶部指向正北。方向角为 90 表示地图顶部指向正东方(罗盘上为 90 度)。方向角为 180 表示地图顶部指向正南方。

您可以使用 Maps API 更改地图的方向角。例如,驾车的用户通常会旋转道路地图使其与他们的行驶方向一致,而远足者使用地图和罗盘时通常会调整地图方向,使地图上有一条垂直线指向北方。

倾斜度(视角)

倾斜度是指镜头在地图中心位置正上方圆弧上所处的位置,以相对于天底(相机正下方)的角度来表示。值为 0 时,镜头竖直朝下。值大于 0 时,镜头按指定角度朝地平线倾斜。更改视角时,地图会以透视法呈现:远处的地图项显示得较小,而近处的地图项显示得较大。以下插图展示了这种情况。

在下面的图片中,视角为 0 度。第一张图片是视角为 0 度时的示意图;位置 1 是镜头位置,位置 2 是当前的地图位置。生成的地图如下所示。

镜头视角为 0 度、缩放级别为 18 的地图的屏幕截图。
以镜头的默认视角显示的地图。
显示镜头默认位置(在地图位置正上方,角度为 0)的示意图。
镜头的默认视角。

以下图片中的视角为 45 度。请注意,镜头沿圆弧移到了正上(0 度)与地面(90 度)中间的位置,也就是位置 3。镜头仍指向地图的中心点,但现在位置 4 处的线表示的区域会显示出来。

镜头视角为 45 度、缩放级别为 18 的地图的屏幕截图。
以 45 度视角显示的地图。
显示镜头的视角设置为 45 度、缩放级别仍设置为 18 的示意图。
45 度镜头视角。

此屏幕截图中的地图仍与原始地图采用同一个中心点,但地图顶部显示的地图项增加了。当您将角度增加到 45 度以上时,镜头和地图位置之间的地图项会按比例显示得较大,而地图位置远处的地图项会按比例显示得较小,从而产生三维效果。

缩放级别

镜头的缩放级别决定了地图的比例。缩放级别越大,屏幕上显示的信息越详细;缩放级别越小,屏幕上显示的世界范围越广。 缩放级别为 0 时,地图的比例为:整个世界的宽度约为 256 个点。

缩放级别每增加 1 个级别,屏幕上地球的宽度就会翻一番。因此,当缩放级别为 N 时,地球的宽度约为 256 * 2N 个点。例如,缩放级别为 2 时,整个地球的宽度大约为 1024 个点。

缩放级别的值不必是整数。地图允许的缩放级别范围取决于多个因素,包括目标、地图类型和屏幕尺寸。超出该范围的任何数值都将转换为最接近的有效值(可以是最小缩放级别或最大缩放级别)。以下列表显示了您在每个缩放级别看到的地图的大致详细程度:

  • 1:世界
  • 5:大陆/洲
  • 10:城市
  • 15:街道
  • 20:建筑物
以下图片显示了不同缩放级别的视觉外观:
缩放级别为 5 的地图的屏幕截图
缩放级别为 5 的地图。
缩放级别为 15 的地图的屏幕截图
缩放级别为 15 的地图。
缩放级别为 20 的地图的屏幕截图
缩放级别为 20 的地图。

设置初始摄像头位置

使用 GMSCameraPosition 对象设置初始相机位置,以便设置目标的纬度和经度以及方位、倾斜度和缩放。

如需设置初始摄像头位置,请创建一个 GMSMapViewOptions 对象,并将 camera 属性设置为 GMSCameraPosition。然后,将选项传递给 GMSMapView 便捷构造函数。

Swift

let options = GMSMapViewOptions()
options.camera = GMSCameraPosition.camera(withLatitude: -33.8683, longitude: 151.2086, zoom: 16)
let mapView = GMSMapView(options:options)

Objective-C

GMSMapViewOptions *options = [[GMSMapViewOptions alloc] init];
options.camera = [GMSCameraPosition cameraWithLatitude:-33.8683
                                                        longitude:151.2086
                                                             zoom:16];
GMSMapView *mapView = [[GMSMapView alloc] initWithOptions:options];

您还可以使用默认的 UIView init 方法创建 GMSMapView 对象。在这种情况下,摄像头的位置一开始将处于默认位置,您可以在创建后更改它。

Swift

let options = GMSMapViewOptions()
options.frame = self.view.bounds
let mapView = GMSMapView(options:options)

Objective-C

GMSMapViewOptions *options = [[GMSMapViewOptions alloc] init];
options.frame = self.view.bounds;
GMSMapView *mapView = [[GMSMapView alloc] initWithOptions:options];

更改摄像头位置

您可以以编程方式更改相机位置,以设置位置、方位、倾斜度和缩放级别。虽然 GMSMapView 提供了多种用于更改相机位置的方法,但您通常使用 GMSCameraPositionGMSCameraUpdate

  • GMSCameraPosition 包含用于更改每个相机位置参数(目标、方位、倾斜度和缩放)的属性和方法。

  • 借助 GMSCameraUpdate,您可以更改目标、方位、倾斜度和缩放级别,还包含其他便捷方法,以支持滚动、高级缩放、将摄像头居中放置在预定义边界内等操作。

移动摄像头时,您可以选择将摄像头“贴靠”到新位置(即不显示动画),也可以为移动添加动画效果。例如,如果您为相机目标位置的更改添加动画,动画会从先前的位置平移到新位置。

动画会插入当前镜头属性和新的镜头属性之间。您可以使用核心动画来控制动画的持续时间。

使用 GMSCameraPosition

如需使用 GMSCameraPosition 更改相机,您可以创建新对象或复制现有对象,然后在 GMSMapView 对象上进行设置。使用 GMSCameraPosition 对象将摄像头贴靠到新的位置(可以带动画,也可以不带动画)。

使用 GMSCameraPosition 对象可配置任何相机属性,例如纬度、经度、缩放级别、方位和视角。然后,您可以使用该对象设置 GMSMapViewcamera 属性。

Swift

let fancy = GMSCameraPosition(
  latitude: -33,
  longitude: 151,
  zoom: 6,
  bearing: 270,
  viewingAngle: 45
)
mapView.camera = fancy
      

Objective-C

GMSCameraPosition *fancy = [GMSCameraPosition cameraWithLatitude:-33.8683
                                                       longitude:151.2086
                                                            zoom:6
                                                         bearing:30
                                                    viewingAngle:45];
[mapView setCamera:fancy];
      

省略您要设置为默认值的所有 GMSCameraPosition 属性。

如需为移动添加动画效果,请使用 animateToCameraPosition: 方法,而不是设置 camera 属性。

使用 GMSCameraUpdate

借助 GMSCameraUpdate,您可以更新摄像头位置,并选择是将摄像头贴靠到新位置还是以动画方式移动到新位置。GMSCameraUpdate 的优势在于便捷。您可以使用 GMSCameraPosition 执行与 GMSCameraUpdate 相同的任务,但 GMSCameraUpdate 提供了其他辅助方法,可让您更轻松地操控摄像头。

例如,如需使用 GMSCameraPosition 递增当前缩放级别,您必须先确定当前缩放级别,然后创建一个 GMSCameraPosition 对象,并将缩放级别设置为比当前缩放级别大 1 的值。

或者,您也可以使用 zoomIn: 方法构建 GMSCameraUpdate 对象。然后,通过将 GMSCameraUpdate 对象传递给 GMSMapView animateWithCameraUpdate: 方法来更新摄像头。

Swift

// Zoom in one zoom level
let zoomCamera = GMSCameraUpdate.zoomIn()
mapView.animate(with: zoomCamera)
      

Objective-C

// Zoom in one zoom level
GMSCameraUpdate *zoomCamera = [GMSCameraUpdate zoomIn];
[mapView animateWithCameraUpdate:zoomCamera];
      

请改用 GMSMapView moveCamera: 方法将相机快速移动到新位置。

在下一个示例中,您将使用 GMSCameraUpdate 为摄像头移动添加动画效果,使其以温哥华为中心。

Swift

// Center the camera on Vancouver, Canada
let vancouver = CLLocationCoordinate2D(latitude: 49.26, longitude: -123.11)
let vancouverCam = GMSCameraUpdate.setTarget(vancouver)
mapView.animate(with: vancouverCam)
      

Objective-C

// Center the camera on Vancouver, Canada
CLLocationCoordinate2D vancouver = CLLocationCoordinate2DMake(49.26, -123.11);
GMSCameraUpdate *vancouverCam = [GMSCameraUpdate setTarget:vancouver];
[mapView animateWithCameraUpdate:vancouverCam];
      

构造 GMSCameraUpdate 对象

使用 GMSCameraUpdate 的其中一个方法构建 GMSCameraUpdate 对象。

zoomIn:zoomOut:
将当前缩放级别增加或减少 1.0,而所有其他属性保持不变。
zoomTo:
将缩放级别更改为给定值,而所有其他属性保持不变。
zoomBy:
使缩放级别增加(如果是负值,则减少)给定值。
zoomBy:atPoint:
使缩放级别增加(如果是负值,则减少)给定值,同时保留指定的点在屏幕上的位置。
setTarget:
更改摄像头的经度和纬度,同时让所有其他属性保持不变。
setTarget:zoom:
更改摄像头的经度、纬度和缩放级别,同时让所有其他属性保持不变。
setCamera:
设置新的 GMSCameraPosition
scrollByX:Y:
更改摄像头的经度和纬度,使地图按指定的点数移动。x 正值会将镜头向右移动,显示出来的效果就是地图向左移动。y 正值会使摄像头下移,带来地图上移的效果。滚动方向是相对于镜头当前方位而言的。例如,如果镜头的方向角为 90 度,那么“上”方就表示东方。
fitBounds:
转换摄像头,使得指定的边界以尽可能最高的缩放级别在屏幕上居中显示。对 64 个点的边界应用默认的内边距。
fitBounds:withPadding:
转换摄像头,使得指定的边界以尽可能最高的缩放级别在屏幕上居中显示。使用此方法可为边框的所有边指定相同的内边距(以点为单位)。
fitBounds:withEdgeInsets:
转换摄像头,使得指定的边界以尽可能最高的缩放级别在屏幕上居中显示。使用 UIEdgeInsets 时,您可以单独为边界框的每一侧指定内边距。

使用 GMSMapView 更改单个属性

GMSMapView 提供了多种方法,可让您在不使用 GMSCameraPosition 对象或 GMSCameraUpdate 对象的情况下移动相机。借助这些方法(例如 animateToLocation:animateToZoom:),您可以为单个摄像头属性的更改添加动画效果。

例如,使用 toViewingAngle: 方法为相机倾斜度的更改添加动画效果。

Swift

mapView.animate(toViewingAngle: 45)
      

Objective-C

[mapView animateToViewingAngle:45];
      

设置目标(位置)

位置决定了地图的中心。位置由经度和纬度来指定,从编程角度来看,位置用 CLLocationCoordinate2D 来表示,通过 CLLocationCoordinate2DMake 来创建。

使用 GMSCameraPosition 更改位置。在此示例中,地图会自动跳转到新位置。

Swift

let target = CLLocationCoordinate2D(latitude: -33.868, longitude: 151.208)
mapView.camera = GMSCameraPosition(target: target, zoom: 6)
      

Objective-C

CLLocationCoordinate2D target =
    CLLocationCoordinate2DMake(-33.868, 151.208);
mapView.camera = [GMSCameraPosition cameraWithTarget:target zoom:6];
      

如需以动画形式呈现更改并将地图平移到新位置,您可以使用 animateToCameraPosition: 方法,而不是设置 camera 属性。或者,对 GMSMapView 使用 animateToLocation: 方法。

Swift

mapView.animate(toLocation: CLLocationCoordinate2D(latitude: -33.868, longitude: 151.208))
      

Objective-C

[mapView animateToLocation:CLLocationCoordinate2DMake(-33.868, 151.208)];
      

您还可以创建 GMSCameraUpdate 对象来移动摄像头。使用其内置方法 scrollByX:Y: 指定在 X 和 Y 方向滚动相机的点数。在此示例中,您将相机向右滚动 200 点,向下滚动 100 点:

Swift

// Move the camera 200 points to the right, and 100 points downwards
let downwards = GMSCameraUpdate.scrollBy(x: 200, y: 100)
mapView.animate(with: downwards)
      

Objective-C

// Move the camera 200 points to the right, and 100 points downwards
GMSCameraUpdate *downwards = [GMSCameraUpdate scrollByX:200.0 Y:100.0];
[mapView animateWithCameraUpdate:downwards];
      

设置方向角(方向)

方向角是地图顶部边缘的罗盘方向,以相对于正北方的角度来表示。例如,在方位为 90 度的地图中,顶部边缘指向正东。

使用 GMSCameraPositionGMSCameraUpdateGMSMapViewanimateToBearing: 方法以编程方式设置方位。

Swift

mapView.animate(toBearing: 0)
      

Objective-C

[mapView animateToBearing:0];
      

设置倾斜度(视角)

视角是摄像头在地图中心位置正上方与地球表面之间圆弧上所处的位置,用与天底(摄像头正下方)所呈角度(以度为单位)来表示。当您更改视角时,地图会以透视法呈现:摄像头与地图位置之间的地图项显示得较大,而地图位置远处的地图项显示得较小,从而产生三维效果。

视角的范围介于 0(垂直向下指向地图)和与缩放级别相关的最大视角之间。对于缩放级别 16 或更高级别,最大视角为 65 度。对于缩放级别 10 或更低级别,最大视角为 30 度。

使用 GMSCameraPositionGMSCameraUpdateGMSMapViewanimateToViewingAngle: 方法以编程方式设置视角。

Swift

mapView.animate(toViewingAngle: 45)
      

Objective-C

[mapView animateToViewingAngle:45];
      

设置缩放比例

镜头的缩放级别决定了地图的比例。缩放级别越大,屏幕上显示的信息越详细;缩放级别越小,屏幕上显示的范围越广。

使用 GMSCameraPositionGMSCameraUpdateGMSMapViewanimateToZoom: 方法以编程方式设置缩放。

Swift

mapView.animate(toZoom: 12)
      

Objective-C

[mapView animateToZoom:12];
      

以下示例使用 zoomIn: 方法构建 GMSCameraUpdate 对象,以动画形式呈现从当前级别放大一级的变化过程。

Swift

// Zoom in one zoom level
let zoomCamera = GMSCameraUpdate.zoomIn()
mapView.animate(with: zoomCamera)
      

Objective-C

// Zoom in one zoom level
GMSCameraUpdate *zoomCamera = [GMSCameraUpdate zoomIn];
[mapView animateWithCameraUpdate:zoomCamera];
      

设置边界

如需移动摄像头,以便以尽可能高的缩放级别显示整个感兴趣的区域,请为摄像头视图设置边界。例如,如果您要显示用户当前位置方圆五英里内的所有加油站,则需要移动摄像头,以使所有加油站都显示在屏幕上:

  1. 计算您想在屏幕上显示的 GMSCoordinateBounds
  2. 使用 GMSMapViewcameraForBounds:insets: 方法返回新的 GMSCameraPosition

设置这些边界可确保给定的 GMSCoordinateBounds 完全容纳于当前地图的大小范围之内。请注意,此方法会将地图的倾斜度和方位设置为 0。

以下示例演示了如何更改摄像头,以使温哥华和卡尔加里这两个城市出现在同一个视图中。

Swift

let vancouver = CLLocationCoordinate2D(latitude: 49.26, longitude: -123.11)
let calgary = CLLocationCoordinate2D(latitude: 51.05,longitude: -114.05)
let bounds = GMSCoordinateBounds(coordinate: vancouver, coordinate: calgary)
let camera = mapView.camera(for: bounds, insets: UIEdgeInsets())!
mapView.camera = camera
      

Objective-C

CLLocationCoordinate2D vancouver = CLLocationCoordinate2DMake(49.26, -123.11);
CLLocationCoordinate2D calgary = CLLocationCoordinate2DMake(51.05, -114.05);
GMSCoordinateBounds *bounds =
    [[GMSCoordinateBounds alloc] initWithCoordinate:vancouver coordinate:calgary];
GMSCameraPosition *camera = [mapView cameraForBounds:bounds insets:UIEdgeInsetsZero];
mapView.camera = camera;
      

将用户的平移操作限定在指定区域

在这些情况下,您虽然设置了地图的边界,但是用户仍可以滚动或平移至这些边界外。您不妨改为限制地图焦点(镜头目标)的坐标中心边界,以便用户只能在这些边界内滚动和平移。

例如,购物中心或机场的零售应用可能希望将地图限制在特定边界以内,让用户只能在这些边界内滚动和平移。

如需将平移限制为特定边界,请将 GMSMapViewcameraTargetBounds 属性设置为定义所需边界的 GMSCoordinateBounds 对象。如需稍后移除限制,请将 cameraTargetBounds 设为 nil。

Swift

mapView.cameraTargetBounds = bounds
      

Objective-C

mapView.cameraTargetBounds = bounds;
      

在下图所示的情况下,镜头目标被限制在一个略微大于视口的区域内。只要镜头目标仍然位于边界区域内,用户就可以滚动和平移。叉型记号表示镜头目标:

显示大于视口的摄像头边界的图片。

地图将始终填满视口,即使这会导致视口显示指定边界以外的区域也是如此。例如,如果您将镜头目标定位在边界区域的角上,超出角的区域在视口中仍然可见,但是用户无法滚动到该区域。下图说明了这种情况。叉型记号表示镜头目标:

显示镜头目标定位在镜头边界右下角的示意图。

在下图中,镜头目标具有一个非常有限的边界,这让用户基本无法滚动或平移地图。叉型记号表示镜头目标:

显示小于视口的摄像头边界的图片。

设置最小或最大缩放级别

全局常量 kGMSMinZoomLevelkGMSMaxZoomLevel 用于定义最小或最大缩放值。默认情况下,GMSMapViewminZoommaxZoom 属性会设置为这些常量。

如需限制地图可用的缩放级别范围,请设置最小和最大缩放级别。以下代码将缩放级别限制在 10 到 15 之间。

Swift

let camera = GMSCameraPosition(
  latitude: 41.887,
  longitude: -87.622,
  zoom: 12
)
let mapView = GMSMapView(frame: .zero, camera: camera)
mapView.setMinZoom(10, maxZoom: 15)
      

Objective-C

GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:41.887
                                                       longitude:-87.622
                                                             zoom:12];
GMSMapView *mapView = [GMSMapView mapWithFrame:CGRectZero
                                        camera:camera];
[mapView setMinZoom:10 maxZoom:15];
      

您必须使用 setMinZoom:maxZoom: 方法设置缩放范围;不过,您可以使用 minZoommaxZoom 属性读取当前值。当只限制其中一个值时,这种方法非常有用。以下代码只更改最小缩放级别。

Swift

mapView.setMinZoom(12, maxZoom: mapView.maxZoom)
      

Objective-C

[mapView setMinZoom:12 maxZoom:mapView.maxZoom];
      

如果在更新最小和最大缩放后,摄像头的缩放级别被设置为超出新范围之外的某个值,则当前缩放将自动更新以显示最接近的有效值。例如,在以下代码中,原始缩放级别定义为 4。后来将缩放范围设置为 10-15 时,当前缩放将更新为 10。

Swift

// Sets the zoom level to 4.
let camera2 = GMSCameraPosition(
  latitude: 41.887,
  longitude: -87.622,
  zoom: 4
)
let mapView2 = GMSMapView(frame: .zero, camera: camera)

// The current zoom, 4, is outside of the range. The zoom will change to 10.
mapView.setMinZoom(10, maxZoom: 15)
      

Objective-C

// Sets the zoom level to 4.
GMSCameraPosition *camera2 = [GMSCameraPosition cameraWithLatitude:41.887
                                                         longitude:-87.622
                                                              zoom:4];
GMSMapView *mapView2 = [GMSMapView mapWithFrame:CGRectZero
                                         camera:camera];
// The current zoom, 4, is outside of the range. The zoom will change to 10.
[mapView setMinZoom:10 maxZoom:15];