第三篇:地图控制与UI设置
本篇教程将学习如何切换地图类型、配置UI控件,以及监听地图事件。
学习目标
- 掌握地图类型切换(标准、卫星、夜间等)
- 配置地图UI控件(缩放按钮、指南针、比例尺)
- 监听地图事件(点击、长按、相机变化)
- 控制地图手势(缩放、旋转、倾斜)
1. 地图类型
高德地图支持多种地图类型:
| 类型 | 常量 | 说明 |
|---|---|---|
| 标准地图 | MapType.MAP_TYPE_NORMAL |
默认类型,显示道路和地标 |
| 卫星地图 | MapType.MAP_TYPE_SATELLITE |
显示卫星图像 |
| 夜间地图 | MapType.MAP_TYPE_NIGHT |
深色主题,适合夜间使用 |
| 导航地图 | MapType.MAP_TYPE_NAVI |
导航场景专用 |
| 导航夜间 | MapType.MAP_TYPE_NAVI_NIGHT |
导航夜间模式 |
| 公交地图 | MapType.MAP_TYPE_BUS |
突出显示公交线路 |
2. 完整代码示例
创建文件 entry/src/main/ets/pages/Demo02_MapControl.ets:
typescript
import {
AMap,
MapView,
MapViewComponent,
MapViewManager,
MapViewCreateCallback,
MapType,
CameraPosition,
LatLng,
OnCameraChangeListener,
Poi,
UiSettings
} from '@amap/amap_lbs_map3d';
const MAP_VIEW_NAME = 'MapControlDemo';
/**
* 地图类型选项
*/
interface MapTypeOption {
name: string;
type: MapType;
}
@Entry
@Component
struct Demo02_MapControl {
private mapView: MapView | undefined = undefined;
private aMap: AMap | undefined = undefined;
private uiSettings: UiSettings | undefined = undefined;
@State isMapReady: boolean = false;
@State currentMapType: string = '标准地图';
@State cameraInfo: string = '';
@State clickInfo: string = '点击地图查看坐标';
// UI控件状态
@State showZoomControls: boolean = true;
@State showCompass: boolean = true;
@State showScaleControls: boolean = true;
@State enableZoomGesture: boolean = true;
@State enableRotateGesture: boolean = true;
@State enableTiltGesture: boolean = true;
// 地图类型选项
private mapTypes: MapTypeOption[] = [
{ name: '标准地图', type: MapType.MAP_TYPE_NORMAL },
{ name: '卫星地图', type: MapType.MAP_TYPE_SATELLITE },
{ name: '夜间地图', type: MapType.MAP_TYPE_NIGHT },
{ name: '导航地图', type: MapType.MAP_TYPE_NAVI },
{ name: '公交地图', type: MapType.MAP_TYPE_BUS }
];
private mapViewCreateCallback: MapViewCreateCallback =
(mapview: MapView | undefined, mapViewName: string | undefined) => {
if (!mapview || mapViewName !== MAP_VIEW_NAME) return;
this.mapView = mapview;
this.mapView.onCreate();
this.mapView.getMapAsync((map: AMap) => {
this.aMap = map;
this.uiSettings = map.getUiSettings();
this.isMapReady = true;
// 设置事件监听
this.setupEventListeners();
// 初始化UI设置
this.applyUiSettings();
});
};
/**
* 设置事件监听器
*/
private setupEventListeners(): void {
if (!this.aMap) return;
// 1. 地图点击事件
this.aMap.setOnMapClickListener((point: LatLng) => {
console.info('[MapControl] Map clicked:', point.latitude, point.longitude);
this.clickInfo = `点击: ${point.latitude.toFixed(6)}, ${point.longitude.toFixed(6)}`;
});
// 2. 地图长按事件
this.aMap.setOnMapLongClickListener((point: LatLng) => {
console.info('[MapControl] Map long clicked:', point.latitude, point.longitude);
this.clickInfo = `长按: ${point.latitude.toFixed(6)}, ${point.longitude.toFixed(6)}`;
});
// 3. 相机变化事件
this.aMap.setOnCameraChangeListener(new OnCameraChangeListener(
// 相机移动中
(position: CameraPosition) => {
this.updateCameraInfo(position);
},
// 相机移动结束
(position: CameraPosition) => {
this.updateCameraInfo(position);
console.info('[MapControl] Camera change finished');
}
));
// 4. POI点击事件
this.aMap.addOnPOIClickListener((poi: Poi) => {
const name = poi.getName();
const poiId = poi.getPoiId();
const coordinate = poi.getCoordinate();
console.info('[MapControl] POI clicked:', name, poiId);
if (coordinate) {
this.clickInfo = `POI: ${name}\n${coordinate.latitude.toFixed(6)}, ${coordinate.longitude.toFixed(6)}`;
}
});
// 5. 地图触摸事件
this.aMap.setOnMapTouchListener((event: TouchEvent) => {
// 可以获取触摸坐标进行自定义处理
// console.info('[MapControl] Touch:', event.touches[0].x, event.touches[0].y);
});
}
/**
* 更新相机信息
*/
private updateCameraInfo(position: CameraPosition): void {
const target = position.target;
this.cameraInfo = `经度: ${target.longitude.toFixed(4)}\n纬度: ${target.latitude.toFixed(4)}\n缩放: ${position.zoom.toFixed(1)}\n旋转: ${position.bearing.toFixed(0)}°\n倾斜: ${position.tilt.toFixed(0)}°`;
}
/**
* 应用UI设置
*/
private applyUiSettings(): void {
if (!this.uiSettings) return;
// 缩放控件
this.uiSettings.setZoomControlsEnabled(this.showZoomControls);
// 指南针
this.uiSettings.setCompassEnabled(this.showCompass);
// 比例尺
this.uiSettings.setScaleControlsEnabled(this.showScaleControls);
// 缩放手势
this.uiSettings.setZoomGesturesEnabled(this.enableZoomGesture);
// 旋转手势
this.uiSettings.setRotateGesturesEnabled(this.enableRotateGesture);
// 倾斜手势
this.uiSettings.setTiltGesturesEnabled(this.enableTiltGesture);
}
/**
* 切换地图类型
*/
private setMapType(option: MapTypeOption): void {
if (!this.aMap) return;
this.aMap.setMapType(option.type);
this.currentMapType = option.name;
console.info('[MapControl] Map type changed to:', option.name);
}
aboutToAppear(): void {
MapViewManager.getInstance()
.registerMapViewCreatedCallback(this.mapViewCreateCallback);
}
aboutToDisappear(): void {
MapViewManager.getInstance()
.unregisterMapViewCreatedCallback(this.mapViewCreateCallback);
if (this.mapView) {
this.mapView.onDestroy();
this.mapView = undefined;
this.aMap = undefined;
}
}
build() {
Column() {
// 标题栏
Row() {
Text('地图控制与UI设置')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor(Color.White)
}
.width('100%')
.height(50)
.padding({ left: 16 })
.backgroundColor('#2196F3')
// 地图区域
Stack() {
MapViewComponent({ mapViewName: MAP_VIEW_NAME })
.width('100%')
.height('100%')
// 相机信息面板
if (this.isMapReady && this.cameraInfo) {
Column() {
Text('相机状态')
.fontSize(12)
.fontWeight(FontWeight.Bold)
.fontColor('#333')
Text(this.cameraInfo)
.fontSize(11)
.fontColor('#666')
.margin({ top: 4 })
}
.padding(8)
.backgroundColor('rgba(255,255,255,0.9)')
.borderRadius(8)
.position({ x: 10, y: 10 })
}
// 点击信息
if (this.isMapReady) {
Text(this.clickInfo)
.fontSize(12)
.fontColor('#333')
.padding(8)
.backgroundColor('rgba(255,255,255,0.9)')
.borderRadius(8)
.position({ x: 10, y: 130 })
}
}
.width('100%')
.height('50%')
// 控制面板
Scroll() {
Column() {
// 地图类型选择
Text('地图类型')
.fontSize(14)
.fontWeight(FontWeight.Bold)
.width('100%')
.margin({ bottom: 8 })
Flex({ wrap: FlexWrap.Wrap }) {
ForEach(this.mapTypes, (option: MapTypeOption) => {
Button(option.name)
.fontSize(12)
.height(32)
.backgroundColor(this.currentMapType === option.name ? '#2196F3' : '#e0e0e0')
.fontColor(this.currentMapType === option.name ? Color.White : '#333')
.margin({ right: 8, bottom: 8 })
.onClick(() => this.setMapType(option))
})
}
.margin({ bottom: 16 })
// UI控件开关
Text('UI控件')
.fontSize(14)
.fontWeight(FontWeight.Bold)
.width('100%')
.margin({ bottom: 8 })
this.buildToggleRow('缩放按钮', this.showZoomControls, (value: boolean) => {
this.showZoomControls = value;
this.uiSettings?.setZoomControlsEnabled(value);
})
this.buildToggleRow('指南针', this.showCompass, (value: boolean) => {
this.showCompass = value;
this.uiSettings?.setCompassEnabled(value);
})
this.buildToggleRow('比例尺', this.showScaleControls, (value: boolean) => {
this.showScaleControls = value;
this.uiSettings?.setScaleControlsEnabled(value);
})
// 手势控制
Text('手势控制')
.fontSize(14)
.fontWeight(FontWeight.Bold)
.width('100%')
.margin({ top: 16, bottom: 8 })
this.buildToggleRow('缩放手势', this.enableZoomGesture, (value: boolean) => {
this.enableZoomGesture = value;
this.uiSettings?.setZoomGesturesEnabled(value);
})
this.buildToggleRow('旋转手势', this.enableRotateGesture, (value: boolean) => {
this.enableRotateGesture = value;
this.uiSettings?.setRotateGesturesEnabled(value);
})
this.buildToggleRow('倾斜手势', this.enableTiltGesture, (value: boolean) => {
this.enableTiltGesture = value;
this.uiSettings?.setTiltGesturesEnabled(value);
})
}
.padding(16)
.width('100%')
.alignItems(HorizontalAlign.Start)
}
.layoutWeight(1)
.backgroundColor('#fafafa')
}
.width('100%')
.height('100%')
}
/**
* 构建开关行
*/
@Builder
buildToggleRow(label: string, value: boolean, onChange: (value: boolean) => void) {
Row() {
Text(label)
.fontSize(14)
.fontColor('#333')
Blank()
Toggle({ type: ToggleType.Switch, isOn: value })
.onChange(onChange)
}
.width('100%')
.height(44)
.padding({ left: 12, right: 12 })
.backgroundColor(Color.White)
.borderRadius(8)
.margin({ bottom: 8 })
}
}
3. UiSettings 完整方法列表
typescript
interface UiSettings {
// 缩放控件
setZoomControlsEnabled(enabled: boolean): void;
isZoomControlsEnabled(): boolean;
// 指南针
setCompassEnabled(enabled: boolean): void;
isCompassEnabled(): boolean;
// 比例尺
setScaleControlsEnabled(enabled: boolean): void;
isScaleControlsEnabled(): boolean;
// 缩放手势
setZoomGesturesEnabled(enabled: boolean): void;
isZoomGesturesEnabled(): boolean;
// 滑动手势
setScrollGesturesEnabled(enabled: boolean): void;
isScrollGesturesEnabled(): boolean;
// 旋转手势
setRotateGesturesEnabled(enabled: boolean): void;
isRotateGesturesEnabled(): boolean;
// 倾斜手势
setTiltGesturesEnabled(enabled: boolean): void;
isTiltGesturesEnabled(): boolean;
// 所有手势
setAllGesturesEnabled(enabled: boolean): void;
// 缩放控件位置
setZoomPosition(position: number): void;
// Logo位置
setLogoPosition(position: number): void;
}
4. 地图事件监听详解
4.1 点击事件
typescript
// 普通点击
aMap.setOnMapClickListener((point: LatLng) => {
console.log('点击坐标:', point.latitude, point.longitude);
});
// 长按
aMap.setOnMapLongClickListener((point: LatLng) => {
console.log('长按坐标:', point.latitude, point.longitude);
});
// POI点击
aMap.addOnPOIClickListener((poi: Poi) => {
console.log('POI名称:', poi.getName());
console.log('POI ID:', poi.getPoiId());
});
4.2 相机变化事件
typescript
aMap.setOnCameraChangeListener(new OnCameraChangeListener(
// 移动中回调(频繁触发)
(position: CameraPosition) => {
console.log('移动中:', position.target);
},
// 移动结束回调
(position: CameraPosition) => {
console.log('移动结束:', position.target);
}
));
4.3 CameraPosition 属性
typescript
interface CameraPosition {
target: LatLng; // 中心点坐标
zoom: number; // 缩放级别 (3-20)
bearing: number; // 旋转角度 (0-360)
tilt: number; // 倾斜角度 (0-60)
}
5. 缩放控件位置配置
typescript
import { AMapOptions } from '@amap/amap_lbs_map3d';
// 设置缩放控件位置
uiSettings.setZoomPosition(AMapOptions.ZOOM_POSITION_RIGHT_CENTER); // 右侧中间
uiSettings.setZoomPosition(AMapOptions.ZOOM_POSITION_RIGHT_BUTTOM); // 右下角
6. 实用技巧
6.1 禁止地图移动
typescript
// 锁定地图,禁止所有手势
uiSettings.setAllGesturesEnabled(false);
6.2 只允许缩放
typescript
uiSettings.setZoomGesturesEnabled(true);
uiSettings.setScrollGesturesEnabled(false);
uiSettings.setRotateGesturesEnabled(false);
uiSettings.setTiltGesturesEnabled(false);
6.3 重置地图方向
typescript
// 重置为正北方向
const position = new CameraPosition(
aMap.getCameraPosition().target,
aMap.getCameraPosition().zoom,
0, // bearing = 0 表示正北
0 // tilt = 0 表示垂直向下看
);
aMap.animateCamera(CameraUpdateFactory.newCameraPosition(position));
本篇小结
本篇教程我们学习了:
- ✅ 6种地图类型及切换方法
- ✅ UI控件的显示与隐藏
- ✅ 手势控制配置
- ✅ 地图事件监听(点击、长按、相机变化)
- ✅ CameraPosition相机参数
下一篇我们将学习如何在地图上添加标记(Marker)。
班级
源码地址