借助 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 是当前的地图位置。生成的地图如下所示。
以下图片中的视角为 45 度。请注意,镜头沿圆弧移到了正上(0 度)与地面(90 度)中间的位置,也就是位置 3。镜头仍指向地图的中心点,但现在位置 4 处的线表示的区域会显示出来。
此屏幕截图中的地图仍与原始地图采用同一个中心点,但地图顶部显示的地图项增加了。当您将角度增加到 45 度以上时,镜头和地图位置之间的地图项会按比例显示得较大,而地图位置远处的地图项会按比例显示得较小,从而产生三维效果。
放大
镜头的缩放级别决定了地图的比例。缩放级别越大,屏幕上显示的信息越详细;缩放级别越小,屏幕上显示的范围越广。 缩放级别为 0 时,地图的比例为:整个世界的宽度约为 256 个点。
缩放级别每增加 1 个级别,屏幕上地球的宽度就会翻一番。因此,当缩放级别为 N 时,地球的宽度约为 256 * 2N 个点。例如,缩放级别为 2 时,整个地球的宽度大约为 1024 个点。
缩放级别的值不必是整数。地图允许的缩放级别范围取决于多个因素,包括目标、地图类型和屏幕尺寸。超出该范围的任何数值都将转换为最接近的有效值(可以是最小缩放级别或最大缩放级别)。以下列表显示了您在每个缩放级别看到的地图的大致详细程度:
- 1:世界
- 5:大陆/洲
- 10:城市
- 15:街道
- 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
提供了几种可用于更改镜头位置的方法,但您通常使用 GMSCameraPosition
或 GMSCameraUpdate
:
GMSCameraPosition
包含用于更改每个镜头位置参数(目标、方位、倾斜度和缩放级别)的属性和方法。GMSCameraUpdate
可让您更改目标、方位、倾斜度和缩放,还包含其他便捷方法,支持滚动、高级缩放、使镜头在预定义的边界内居中等。
当您移动镜头时,可以选择将镜头“紧贴”到新位置(这意味着镜头没有动画效果),或以动画方式移动镜头。例如,如果您为镜头目标位置的变化添加动画效果,则动画会从较早的位置平移到新位置。
动画会插入当前镜头属性和新的镜头属性之间。您可以使用核心动画来控制动画的时长。
使用 GMSCameraPosition
如需使用 GMSCameraPosition
更改镜头,请创建一个新对象或复制现有对象,然后在 GMSMapView
对象上进行设置。使用 GMSCameraPosition
对象将相机贴靠到新位置(无论是否带有动画效果)。
您可以使用 GMSCameraPosition
对象配置任何镜头属性,如纬度、经度、缩放级别、方向角和视角。然后,您可以使用该对象来设置 GMSMapView
的 camera
属性。
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
对象,将缩放级别设置为大于当前缩放级别的值。
或者,使用 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
对象之一构造该对象。
- “
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];
设置目标(位置)
位置决定了地图的中心。位置由纬度和经度指定,并由使用 CLLocationCoordinate2DMake
创建的 CLLocationCoordinate2D
以编程方式表示。
使用 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 度,则地图的顶边缘指向正东方。
使用 GMSCameraPosition
或 GMSCameraUpdate
或使用 GMSMapView
的 animateToBearing:
方法以编程方式设置方位。
Swift
mapView.animate(toBearing: 0)
Objective-C
[mapView animateToBearing:0];
设置倾斜度(视角)
视角是镜头在地图中心位置正上方与地球表面之间圆弧上所处的位置,以与天底(镜头正下方)之间的角度为计量单位。当您更改视角时,地图会以透视法呈现:镜头和地图位置之间的地图项会按比例显示得较大,而地图位置远处的地图项会按比例显示得较小,从而产生三维效果。
视角的范围介于 0(垂直向下指向地图)和与缩放级别相关的最大视角之间。对于缩放级别 16 或更高版本,最大角度为 65 度。对于缩放级别 10 或更低级别,最大角度为 30 度。
使用 GMSCameraPosition
或 GMSCameraUpdate
或使用 GMSMapView
的 animateToViewingAngle:
方法以编程方式设置视角。
Swift
mapView.animate(toViewingAngle: 45)
Objective-C
[mapView animateToViewingAngle:45];
设置缩放级别
镜头的缩放级别决定了地图的比例。缩放级别越大,屏幕上显示的细节就越丰富;缩放级别越小,显示的世界就越广。
使用 GMSCameraPosition
或 GMSCameraUpdate
或者使用 GMSMapView
的 animateToZoom:
方法以编程方式设置缩放。
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];
设置边界
如需移动相机,以尽可能最高的缩放级别显示整个感兴趣的区域,请为相机视图设置边界。例如,如果您想显示用户当前所在位置五英里内的所有加油站,请移动摄像头,使所有加油站都显示在屏幕上:
- 计算您希望在屏幕上显示的
GMSCoordinateBounds
。 - 使用
GMSMapView
的cameraForBounds: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;
将用户的平移限制在给定区域
这些场景设置了地图的边界,但用户随后可以在这些边界之外滚动或平移。您可以改为限制地图焦点(镜头目标)的坐标中心边界,以便用户只能在这些边界内滚动和平移。
例如,购物中心或机场的零售应用可能希望将地图限制在特定边界内,以便用户在这些边界内滚动和平移。
如需将平移限制在特定边界内,请将 GMSMapView
的 cameraTargetBounds
属性设置为用于定义所需边界的 GMSCoordinateBounds
对象。如需稍后移除该限制,请将 cameraTargetBounds
设置为 nil。
Swift
mapView.cameraTargetBounds = bounds
Objective-C
mapView.cameraTargetBounds = bounds;
在下图所示的情况下,镜头目标被限制在一个略微大于视口的区域内。只要镜头目标仍然位于边界区域内,用户就可以滚动和平移。叉型记号表示镜头目标:
地图将始终填满视口,即使这会导致视口显示指定边界以外的区域也是如此。例如,如果您将镜头目标定位在边界区域的角上,超出角的区域在视口中仍然可见,但是用户无法滚动到该区域。下图说明了这种情况。叉型记号表示镜头目标:
在下图中,镜头目标具有非常有限的边界,这让用户基本无法滚动或平移地图。叉型记号表示镜头目标:
设置最小或最大缩放级别
全局常量 kGMSMinZoomLevel
和 kGMSMaxZoomLevel
定义最小或最大缩放值。默认情况下,GMSMapView
的 minZoom
和 maxZoom
属性设置为这些常量。
如需限制地图可用的缩放级别范围,请设置最小和最大缩放级别。以下代码将缩放级别的范围限制为 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:
方法设置缩放范围;不过,您可以使用 minZoom
和 maxZoom
属性读取当前值。如果只限制其中一个值,此方法会很有用。以下代码只会更改最小缩放级别。
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];