第13章 - 导航与视图控制
第13章:导航与视图控制
13.1 Navigator 概述
Navigator 是 Mapsui 中控制地图视角的核心组件,提供了丰富的导航方法。
public class Navigator
{
public Viewport Viewport { get; }
public MMinMax? ZoomLimits { get; set; }
public MRect? PanLimits { get; set; }
public bool RotationLock { get; set; }
// 缩放方法
public void ZoomIn();
public void ZoomOut();
public void ZoomTo(double resolution);
public void ZoomToBox(MRect extent);
// 平移方法
public void CenterOn(double x, double y);
public void CenterOn(MPoint center);
// 旋转方法
public void RotateTo(double rotation);
// 动画导航
public void CenterOnAndZoomTo(MPoint center, double resolution, long duration = 0);
public void FlyTo(MRect extent, long duration = 500);
}
13.2 缩放控制
13.2.1 基本缩放
// 放大一级
map.Navigator.ZoomIn();
// 缩小一级
map.Navigator.ZoomOut();
// 缩放到指定分辨率
map.Navigator.ZoomTo(1000); // 1000 米/像素
// 缩放到指定缩放级别
public void ZoomToLevel(int level)
{
var resolution = ZoomLevelResolutions.GetResolution(level);
map.Navigator.ZoomTo(resolution);
}
13.2.2 缩放到范围
// 缩放到指定范围
var extent = new MRect(minX, minY, maxX, maxY);
map.Navigator.ZoomToBox(extent);
// 缩放到要素范围
public void ZoomToFeatures(IEnumerable<IFeature> features)
{
var extent = GetFeaturesExtent(features);
if (extent != null)
{
map.Navigator.ZoomToBox(extent, MBoxFit.Fit);
}
}
// 缩放到图层范围
public void ZoomToLayer(ILayer layer)
{
var extent = layer.Extent;
if (extent != null)
{
map.Navigator.ZoomToBox(extent);
}
}
13.2.3 缩放限制
// 设置缩放范围限制
map.Navigator.ZoomLimits = new MMinMax(
minResolution: 0.5, // 最大放大(最小分辨率)
maxResolution: 100000 // 最小缩小(最大分辨率)
);
// 基于缩放级别设置限制
map.Navigator.ZoomLimits = new MMinMax(
ZoomLevelResolutions.GetResolution(19), // 最大放大到 19 级
ZoomLevelResolutions.GetResolution(2) // 最小缩小到 2 级
);
13.3 平移控制
13.3.1 定位到指定点
// 定位到坐标点
map.Navigator.CenterOn(centerX, centerY);
// 定位到 MPoint
var center = new MPoint(centerX, centerY);
map.Navigator.CenterOn(center);
// 定位到经纬度
public void CenterOnLonLat(double lon, double lat)
{
var mercator = SphericalMercator.FromLonLat(lon, lat);
map.Navigator.CenterOn(mercator.X, mercator.Y);
}
13.3.2 平移限制
// 限制地图平移范围
var chinaBounds = CoordinateConverter.LonLatExtentToMercator(73, 18, 135, 54);
map.Navigator.PanLimits = chinaBounds;
// 移除平移限制
map.Navigator.PanLimits = null;
13.4 旋转控制
13.4.1 设置旋转角度
// 旋转到指定角度(弧度)
map.Navigator.RotateTo(Math.PI / 4); // 旋转 45 度
// 旋转到指定角度(度数)
public void RotateToDegrees(double degrees)
{
var radians = degrees * Math.PI / 180;
map.Navigator.RotateTo(radians);
}
// 重置旋转
map.Navigator.RotateTo(0);
13.4.2 旋转锁定
// 锁定旋转(禁止用户旋转地图)
map.Navigator.RotationLock = true;
// 允许旋转
map.Navigator.RotationLock = false;
13.5 动画导航
13.5.1 带动画的定位
// 带动画的定位和缩放
var center = new MPoint(centerX, centerY);
map.Navigator.CenterOnAndZoomTo(center, resolution, duration: 500);
// 飞行到指定范围
map.Navigator.FlyTo(extent, duration: 1000);
// 平滑动画定位
public async Task AnimateTo(MPoint target, double targetResolution, int durationMs = 500)
{
var startCenter = new MPoint(
map.Navigator.Viewport.CenterX,
map.Navigator.Viewport.CenterY
);
var startResolution = map.Navigator.Viewport.Resolution;
var startTime = DateTime.Now;
while (true)
{
var elapsed = (DateTime.Now - startTime).TotalMilliseconds;
var progress = Math.Min(elapsed / durationMs, 1.0);
// 使用缓动函数
var easedProgress = EaseOutCubic(progress);
var currentX = startCenter.X + (target.X - startCenter.X) * easedProgress;
var currentY = startCenter.Y + (target.Y - startCenter.Y) * easedProgress;
var currentRes = startResolution + (targetResolution - startResolution) * easedProgress;
map.Navigator.CenterOnAndZoomTo(new MPoint(currentX, currentY), currentRes);
if (progress >= 1.0) break;
await Task.Delay(16); // ~60 FPS
}
}
private double EaseOutCubic(double t)
{
return 1 - Math.Pow(1 - t, 3);
}
13.6 视口查询
13.6.1 获取当前视口信息
// 获取视口信息
var viewport = map.Navigator.Viewport;
// 中心点
var centerX = viewport.CenterX;
var centerY = viewport.CenterY;
// 分辨率
var resolution = viewport.Resolution;
// 旋转角度
var rotation = viewport.Rotation;
// 可见范围
var extent = viewport.Extent;
// 视口大小
var width = viewport.Width;
var height = viewport.Height;
13.6.2 坐标转换
// 屏幕坐标 → 地图坐标
var worldPoint = viewport.ScreenToWorld(new MPoint(screenX, screenY));
// 地图坐标 → 屏幕坐标
var screenPoint = viewport.WorldToScreen(new MPoint(worldX, worldY));
13.7 导航历史
13.7.1 实现导航历史
public class NavigationHistory
{
private readonly Stack<ViewState> _backStack = new();
private readonly Stack<ViewState> _forwardStack = new();
private readonly Navigator _navigator;
public bool CanGoBack => _backStack.Count > 1;
public bool CanGoForward => _forwardStack.Count > 0;
public NavigationHistory(Navigator navigator)
{
_navigator = navigator;
}
public void SaveState()
{
var viewport = _navigator.Viewport;
_backStack.Push(new ViewState
{
CenterX = viewport.CenterX,
CenterY = viewport.CenterY,
Resolution = viewport.Resolution,
Rotation = viewport.Rotation
});
_forwardStack.Clear();
}
public void GoBack()
{
if (!CanGoBack) return;
_forwardStack.Push(_backStack.Pop());
var state = _backStack.Peek();
ApplyState(state);
}
public void GoForward()
{
if (!CanGoForward) return;
var state = _forwardStack.Pop();
_backStack.Push(state);
ApplyState(state);
}
private void ApplyState(ViewState state)
{
_navigator.CenterOnAndZoomTo(
new MPoint(state.CenterX, state.CenterY),
state.Resolution,
duration: 300
);
_navigator.RotateTo(state.Rotation);
}
private class ViewState
{
public double CenterX { get; set; }
public double CenterY { get; set; }
public double Resolution { get; set; }
public double Rotation { get; set; }
}
}
13.8 自定义导航控件
13.8.1 导航控制器
public class MapNavigationController
{
private readonly Map _map;
private readonly NavigationHistory _history;
public MapNavigationController(Map map)
{
_map = map;
_history = new NavigationHistory(map.Navigator);
}
public void ZoomIn() => _map.Navigator.ZoomIn();
public void ZoomOut() => _map.Navigator.ZoomOut();
public void ResetNorth() => _map.Navigator.RotateTo(0);
public void GoHome()
{
// 定义默认视图
var homeExtent = CoordinateConverter.LonLatExtentToMercator(73, 18, 135, 54);
_map.Navigator.ZoomToBox(homeExtent);
}
public void ZoomToLocation(double lon, double lat, int zoomLevel = 15)
{
var center = SphericalMercator.FromLonLat(lon, lat);
var resolution = ZoomLevelResolutions.GetResolution(zoomLevel);
_map.Navigator.CenterOnAndZoomTo(
new MPoint(center.X, center.Y),
resolution,
duration: 500
);
}
public void SaveCurrentView() => _history.SaveState();
public void GoBack() => _history.GoBack();
public void GoForward() => _history.GoForward();
}
13.9 本章小结
本章详细介绍了 Mapsui 的导航与视图控制:
- Navigator 概述:核心导航组件
- 缩放控制:放大、缩小、缩放到范围、缩放限制
- 平移控制:定位、平移限制
- 旋转控制:旋转角度、旋转锁定
- 动画导航:平滑过渡效果
- 视口查询:获取当前视口信息
- 导航历史:前进、后退功能
在下一章中,我们将学习性能优化与最佳实践。
13.10 思考与练习
- 实现一个地图书签功能,保存和恢复多个视图。
- 创建一个平滑的飞行动画,支持自定义缓动曲线。
- 实现一个鸟瞰模式,展示 3D 倾斜效果。
- 创建一个小地图控件,显示当前视图在全图中的位置。
- 实现键盘导航控制(方向键平移,+/-缩放)。

浙公网安备 33010602011771号