Skip to content

显示模式与视角

本指南:控制地图相机位置、缩放、2D/3D、地图全览、跟车模式与自动缩放。

功能介绍

CameraController 负责控制地图相机的位置、朝向、缩放、2D/3D 渲染模式,以及 跟车模式自动缩放(Auto-Zoom)。典型场景包括浏览地图、路线全览和导航跟车。

初始化时可通过 MapViewInitConfig.autoZoomLevel 设置自动缩放视野;运行时可通过 setEnableAutoZoomenableFollowVehicleMode(..., useAutoZoom) 控制是否启用自动缩放。工作机制与产品行为见 Auto Zoom

获取入口:

1
val camera = mapView.getCameraController() ?: return

核心接口一览

分类 接口 / 属性 说明
区域适配 showRegion(region) / showRegion(region, marginRect) / showRegion(region, pixelMargins) / showRegion(region, percentageMargins) 将相机移动至能完整显示指定区域
区域适配 showRegionForRoutes(regionForRoutesInfo) 适配一条或多条路线到指定屏幕矩形
区域适配 showRegionForModelInstance(regionForModelInstance) 适配 Shape.Collection 模型实例
位姿控制 position 读写相机位置、姿态、缩放与过渡时间
缩放控制 zoomLevelRange 限定允许的缩放范围
渲染模式 renderMode 当前 2D / 3D 渲染模式
跟车模式 enableFollowVehicleMode(mode, useAutoZoom) 开启跟车
跟车模式 disableFollowVehicle() 关闭跟车
跟车模式 vehicleFollowMode 当前跟车模式(null 表示未跟车)
自动缩放 setEnableAutoZoom(enableAutozoom) 全局开关自动缩放
坐标转换 worldToViewport(location) 经纬度 → 屏幕坐标
坐标转换 viewportToWorld(point) 屏幕坐标 → 经纬度
事件监听 MapView.setOnCurrentRenderModeChangedListener / setOnTargetRenderModeChangedListener 监听 2D/3D 切换

接口详细说明

1. showRegion — 显示指定经纬度区域

showRegion 提供 4 个重载,用于将相机调整到刚好能包含指定 Camera.Region(经纬度包围盒)的位置。其中重载二直接传入视口上的目标矩形;重载三、四通过像素或百分比边距换算为矩形后再适配,便于避让 HMI 面板。

重载一:无边距

1
fun showRegion(region: Camera.Region?)
参数 类型 说明
region Camera.Region? 经纬度包围盒(含 northLatitude / southLatitude / eastLongitude / westLongitude);为 null 时不生效

重载二:Rect 指定视口矩形

1
fun showRegion(region: Camera.Region?, marginRect: Rect)
参数 类型 说明
region Camera.Region? 经纬度包围盒
marginRect android.graphics.Rect 地图 surface 上的目标矩形(像素)。相机会平移、缩放,使 region 完整落在该矩形内;含义与 RegionForRoutesInfo.rect 一致

与边距重载的区别marginRect 使用标准 Rect(left, top, right, bottom) 表示一块矩形区域(须满足 right > leftbottom > top),不是“左/上/右/下四条内边距”。需要按像素或百分比从四边留白时,请用 Margins.Pixels / Margins.Percentages(实现里会先换算成 Rect 再调用引擎)。marginRect.isEmpty 时本次调用会被忽略。与 CameraControllerMapEngineViewDelegate 说明一致:经纬度区域将显示在该矩形内(inside the view rect)。

重载三:像素边距

1
fun showRegion(region: Camera.Region?, pixelMargins: Margins.Pixels)
参数 类型 说明
region Camera.Region? 经纬度包围盒
pixelMargins Margins.Pixels 像素边距;lrPixels 左右,tbPixels 上下

重载四:百分比边距

1
fun showRegion(region: Camera.Region?, percentageMargins: Margins.Percentages)
参数 类型 说明
region Camera.Region? 经纬度包围盒
percentageMargins Margins.Percentages 百分比边距;lrPercentage / tbPercentage 取值 0.0 ~ 1.0

构造 Camera.Region

1
2
3
4
5
6
val region = Camera.Region().apply {
    extend(37.405, -121.978) // 经纬度点 1
    extend(37.412, -121.962) // 经纬度点 2
    // 多次 extend 后即可自动算出包围盒
}
if (region.valid()) camera.showRegion(region)

示例代码(四个重载对照)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import android.graphics.Rect
import com.telenav.map.api.Margins

// 1) 无边距:整幅地图 surface 作为目标区域
camera.showRegion(region)

// 2) Rect:在地图 surface 上指定一块目标矩形(left, top, right, bottom)
val w = mapView.width
val h = mapView.height
val targetRect = Rect(w / 2 - 300, h / 2 - 300, w - 300, h - 300)
camera.showRegion(region, targetRect)

// 3) 像素边距:对称留白(lr = 左右各留、tb = 上下各留,由 SDK 换算为 Rect)
camera.showRegion(region, Margins.Pixels(32.0, 64.0))

// 4) 百分比边距:相对当前视图尺寸(例如左右、上下各 0.20)
camera.showRegion(region, Margins.Percentages(0.20, 0.20))

更多 showRegion 场景示例

以下片段只突出相机调用;业务里通常在「路线全览 / 看 POI 范围」前关闭跟车并视情况关闭 Auto-Zoom,且应在 region != nullregion.valid() 为真时再调用。

由路线 ID 列表得到包围盒并适配(无边距)

1
2
3
val routeIds: List<String> = // 已添加到 mapView 的路线 id
val region = mapView.routesController().region(routeIds)
mapView.cameraController()?.showRegion(region)

路线包围盒 + 百分比边距(导航全览等场景常用)

1
2
3
val region = mapView.routesController().region(routeIds)
mapView.cameraController()
    ?.showRegion(region, Margins.Percentages(0.20, 0.20))

为顶部面板留出固定高度:用 Rect 把有效地图区设为「去掉顶栏后的矩形」

1
2
3
4
5
6
val w = mapView.width
val h = mapView.height
val topBarPx = 200
if (w > 0 && h > topBarPx) {
    mapView.cameraController()?.showRegion(region, Rect(0, topBarPx, w, h))
}

根据多个经纬度点构造 Camera.Region 再带像素边距适配

1
2
3
4
5
6
7
val region = Camera.Region().apply {
    // points 可为 List<LatLon> 等含 latitude/longitude 的点集合
    points.forEach { extend(it.latitude, it.longitude) }
}
if (region.valid()) {
    mapView.cameraController()?.showRegion(region, Margins.Pixels(48.0, 80.0))
}

2. showRegionForRoutes — 适配路线区域

将一条或多条路线在指定屏幕矩形内进行 Pan + Zoom 适配(不旋转)。常用于"路线全览"场景。

效果示意

MapView 地图概览

1
2
3
fun showRegionForRoutes(
    regionForRoutesInfo: RegionForRoutesInfo
)
参数 类型 说明
regionForRoutesInfo RegionForRoutesInfo 路线适配参数集合,详见下表

RegionForRoutesInfo 字段:

字段 类型 默认 说明
routes List<String> 需要纳入视野的路线 ID 列表
rect android.graphics.Rect 屏幕目标矩形:left = x,top = y,width() = 宽度,height() = 高度
gridAligned Boolean false true:以 2D 北朝上方式适配(矩形严格对齐);false:保持当前相机姿态,矩形覆盖区域的外接圆
showFullRouteOverview Boolean false true:包含已驶过的路线段;false:仅显示剩余部分
includeCVP Boolean false true:强制将 CVP 纳入视野
nearestLegMode Boolean false true:仅显示到第一个 waypoint 的路段
annotations List<Annotation>? null 需一同纳入视野的额外 Annotation

注意:该方法不考虑 skew,调用前需将 LayoutControllerhorizontalOffsetverticalOffset 置为 0。

示例代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import android.graphics.Rect

val regionInfo = RegionForRoutesInfo(
    routes = listOf(routeId),
    rect = Rect(0, 0, mapView.width, mapView.height),
    gridAligned = false,
    showFullRouteOverview = true,
    includeCVP = true,
    nearestLegMode = false,
    annotations = null
)

// 重要:先归零 layout offset
mapView.getLayoutController()?.apply {
    setHorizontalOffset(0f)
    setVerticalOffset(0f)
}

val ok = camera.showRegionForRoutes(regionInfo)

更多 showRegionForRoutes 示例

多条路线同一视口内全览

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
val ids = listOf(primaryRouteId, alternateRouteId)
val info = RegionForRoutesInfo(
    routes = ids,
    rect = Rect(0, 0, mapView.width, mapView.height),
    gridAligned = false,
    showFullRouteOverview = true,
    includeCVP = false,
    nearestLegMode = false,
    annotations = null
)
mapView.getLayoutController()?.apply {
    setHorizontalOffset(0f)
    setVerticalOffset(0f)
}
camera.showRegionForRoutes(info)

只在地图下半区域做路线全览(rectshowRegion 的 Rect 语义相同)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
val w = mapView.width
val h = mapView.height
val info = RegionForRoutesInfo(
    routes = listOf(routeId),
    rect = Rect(0, h / 4, w, h),
    gridAligned = true,
    showFullRouteOverview = false,
    includeCVP = true,
    nearestLegMode = false,
    annotations = null
)
mapView.getLayoutController()?.apply {
    setHorizontalOffset(0f)
    setVerticalOffset(0f)
}
camera.showRegionForRoutes(info)

与 Annotation 一并纳入视野

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
val info = RegionForRoutesInfo(
    routes = listOf(routeId),
    rect = Rect(0, 0, mapView.width, mapView.height),
    gridAligned = false,
    showFullRouteOverview = true,
    includeCVP = true,
    nearestLegMode = false,
    annotations = listOf(poiAnnotation, incidentAnnotation)
)
mapView.getLayoutController()?.apply {
    setHorizontalOffset(0f)
    setVerticalOffset(0f)
}
camera.showRegionForRoutes(info)

3. showRegionForModelInstance — 适配模型实例区域

将某个 Shape.Collection 模型实例适配到指定屏幕矩形内。

1
2
3
fun showRegionForModelInstance(
    regionForModelInstance: RegionForModelInstance
)
参数 类型 说明
regionForModelInstance RegionForModelInstance 模型实例适配参数

RegionForModelInstance 字段:

字段 类型 说明
id ShapesController.Id ShapesController.add(...) 返回的形状集合唯一 ID
rect android.graphics.Rect 屏幕目标矩形
gridAligned Boolean RegionForRoutesInfo.gridAligned

示例代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import android.graphics.Rect

val shapesController = mapView.getShapesController() ?: return
val shapeId: ShapesController.Id = shapesController.add(shapeCollection)

val info = RegionForModelInstance(
    id = shapeId,
    rect = Rect(0, 0, mapView.width, mapView.height),
    gridAligned = true
)

// 与 showRegionForRoutes 相同:当前实现不考虑 skew,建议先归零 layout offset
mapView.getLayoutController()?.apply {
    setHorizontalOffset(0f)
    setVerticalOffset(0f)
}

camera.showRegionForModelInstance(info)

更多 showRegionForModelInstance 示例

在指定屏幕矩形内看高亮多边形(gridAligned = false 时按外接圆适配,见 API 说明)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
val w = mapView.width
val h = mapView.height
val info = RegionForModelInstance(
    id = shapeId,
    rect = Rect(w / 4, h / 4, w * 3 / 4, h * 3 / 4),
    gridAligned = false
)
mapView.getLayoutController()?.apply {
    setHorizontalOffset(0f)
    setVerticalOffset(0f)
}
mapView.cameraController()?.showRegionForModelInstance(info)

北朝上 2D 下严格按模型轴对齐包围盒适配(gridAligned = true

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
val info = RegionForModelInstance(
    id = shapeId,
    rect = Rect(0, 0, mapView.width, mapView.height),
    gridAligned = true
)
mapView.getLayoutController()?.apply {
    setHorizontalOffset(0f)
    setVerticalOffset(0f)
}
mapView.cameraController()?.showRegionForModelInstance(info)

4. position — 相机位姿(读写)

通过 Camera.Position 一次性读取或设置相机的位置、姿态、缩放与过渡动画。

接口属性 类型 说明
position(get) Camera.Position 读取当前相机位置
position(set) Camera.Position 写入目标相机位置(不需要的字段保持 null 即可)

Camera.Position.Builder 字段:

方法 参数类型 取值 说明
setLocation(location) Location? 相机中心位置(经纬度)
setBearing(bearing) Float 0f ~ 360f 方位角,0° 正北,180° 正南,逆时针增大
setTilt(tilt) Float 0f ~ 60f 倾角,0° 为完全俯视(2D 视角)
setZoomLevel(zoomLevel) Float 0f ~ 17f 缩放级别,0 为最低(大陆级),17 为最高(街道级)
setZoomTransitionTime(transitionTime) Float 缩放过渡动画时间

示例代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// 平滑飞向某个位置
val target = Location("").apply {
    latitude = 37.7749
    longitude = -122.4194
}

camera.position = Camera.Position.Builder()
    .setLocation(target)
    .setZoomLevel(14f)
    .setBearing(0f)
    .setTilt(0f)
    .setZoomTransitionTime(0.6f)
    .build()

5. renderMode — 2D / 3D 渲染模式

接口属性 类型 说明
renderMode(get) Camera.RenderMode 读取当前渲染模式
renderMode(set) Camera.RenderMode 设置目标渲染模式

Camera.RenderMode 枚举:

说明
M2D 二维模式
M3D 三维模式(默认 tilt ≈ -39°)

示例代码

1
2
3
4
5
// 切到 3D
camera.renderMode = Camera.RenderMode.M3D

// 切回 2D
camera.renderMode = Camera.RenderMode.M2D

6. zoomLevelRange — 限定缩放范围

接口属性 类型 说明
zoomLevelRange android.util.Range<Float> 允许的缩放上下限,外部手势缩放与代码设置都将被夹紧到此范围内

示例代码

1
camera.zoomLevelRange = Range(0f, 18f)

7. enableFollowVehicleMode — 启用跟车模式

1
2
3
4
fun enableFollowVehicleMode(
    mode: Camera.FollowVehicleMode,
    useAutoZoom: Boolean
)
参数 类型 说明
mode Camera.FollowVehicleMode 跟车朝向模式:HeadingUp(车头朝上)/ NorthUp(北朝上)/ Static(不调整朝向/tilt)
useAutoZoom Boolean 跟车过程中是否自动调整缩放;在 M3D 下会同时调整 tilt 突出关键路口

示例代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// 导航中:车头朝上 + Auto-Zoom
camera.enableFollowVehicleMode(
    Camera.FollowVehicleMode.HeadingUp,
    useAutoZoom = true
)

// 路线全览时:北朝上、关闭自动缩放
camera.enableFollowVehicleMode(
    Camera.FollowVehicleMode.NorthUp,
    useAutoZoom = false
)

8. disableFollowVehicle — 关闭跟车

接口方法 说明
disableFollowVehicle() 退出跟车模式,相机不再跟随 CVP 移动;调用后 vehicleFollowMode 变为 null

示例代码

1
camera.disableFollowVehicle()

9. setEnableAutoZoom — 全局开关自动缩放

1
2
3
fun setEnableAutoZoom(
    enableAutozoom: Boolean
)
参数 类型 说明
enableAutozoom Boolean true 启用自动缩放;false 关闭。改变跟车模式本身

示例代码

1
camera.setEnableAutoZoom(true)

10. vehicleFollowMode — 读取当前跟车模式

接口属性 类型 说明
vehicleFollowMode Camera.FollowVehicleMode? 当前跟车模式;为 null 表示未启用跟车

示例代码

1
2
3
4
5
6
7
val isFollowing = camera.vehicleFollowMode != null
when (camera.vehicleFollowMode) {
    Camera.FollowVehicleMode.HeadingUp -> { /* 车头朝上 */ }
    Camera.FollowVehicleMode.NorthUp   -> { /* 北朝上 */ }
    Camera.FollowVehicleMode.Static    -> { /* 静态跟车 */ }
    null -> { /* 未跟车 */ }
}

11. worldToViewport — 经纬度 → 屏幕坐标

1
2
3
fun worldToViewport(
    location: android.location.Location
)
参数 类型 说明
location android.location.Location 要转换的地理位置(含经纬度)

示例代码

1
2
3
4
5
6
val loc = Location("").apply {
    latitude = 37.7749
    longitude = -122.4194
}
val screen: PointF? = camera.worldToViewport(loc)
screen?.let { drawOverlayAt(it.x, it.y) }

12. viewportToWorld — 屏幕坐标 → 经纬度

1
2
3
fun viewportToWorld(
    point: android.graphics.PointF
)
参数 类型 说明
point android.graphics.PointF MapView 上的屏幕坐标(像素)

示例代码

1
2
3
4
5
6
7
mapView.setOnTouchListener { _, ev ->
    if (ev.action == MotionEvent.ACTION_UP) {
        val world = camera.viewportToWorld(PointF(ev.x, ev.y))
        world?.let { onMapTapped(it.latitude, it.longitude) }
    }
    false
}

13. 渲染模式监听

通过 MapView 注册监听 2D/3D 模式切换:

接口 回调 参数类型 说明
CurrentRenderModeChangeListener onCurrentRenderingModeChanged(currentRenderMode) Camera.RenderMode 当前渲染模式 已经 切换完成
TargetRenderModeChangeListener onTargetRenderingModeChanged(targetRenderMode) Camera.RenderMode 渲染模式 即将 切换的目标值

示例代码

1
2
3
4
5
6
7
mapView.setOnCurrentRenderModeChangedListener { current ->
    Log.d(TAG, "render mode changed to $current")
}

mapView.setOnTargetRenderModeChangedListener { target ->
    Log.d(TAG, "render mode is changing to $target")
}

14. AutoZoomLevel(初始化期)

MapViewInitConfigClusterMapViewParams 中通过 autoZoomLevel 设置默认自动缩放视野:

枚举值 说明
DEFAULT 默认视野
MEDIUM 中等视野
FAR 较远视野
VERY_FAR 很远视野
MAXIMUM 最大视野

值越大,自动缩放展示的范围越广。

示例代码

1
2
3
4
5
6
val config = MapViewInitConfig(
    context = context,
    listener = readyListener,
    autoZoomLevel = AutoZoomLevel.FAR
)
mapView.initialize(config)

AutoZoomController 由引擎内部驱动,MapView 上直接暴露;集成方通过 autoZoomLevelCameraController.setEnableAutoZoom 控制即可。

注意事项

  • 所有 CameraController 接口必须在 onReady 之后调用。
  • 跟车模式下若 renderModeM3D,且 useAutoZoom = true,自动缩放可能同时调整 tilt
  • showRegionForRoutes / showRegionForModelInstance 当前不考虑 skew,调用前需将 LayoutController 的 horizontal / vertical offset 置为 0。
  • worldToViewport 在目标点不在可视区域时可能返回 null,调用方需做空值处理。
  • showAutoZoomDebugInfo 等调试 API 非对外集成接口,请勿依赖。

相关指南