可视化-地图鹰眼的设计与实现

地图鹰眼的设计与实现

什么是地图鹰眼?

鹰眼就是展示当前视图范围在全局视图下占据的空间范围。其实就是一个局部视野和全局视野的浏览模式。

如何实现鹰眼效果?

实现思路

  • 首先需要两张地图,分别为 MainMap、MiniMap
  • 其次需要一个鹰眼框 Box,这个框代表了 MainMap 在 MiniMap 的范围,这个框的大小和位置是随着 MainMap 范围的变化而变化的
  • 当移动 MainMap 时,MiniMap 随之变化,并且 Box 大小和位置更新
  • 当移动 Box 时,MainMap 范围也要随之改变

注意的点:

  • MainMap 移动 和 Box 移动都会互相通知对方,要避免陷入死循环
  • MiniMap 不响应用户事件,Box 响应用户事件
  • MiniMap 地理范围应该比 MainMap 大,以容纳下 Box

关键技术

  • 屏幕坐标和地理坐标之间的相互转换
  • HTML 元素拖拽效果的实现

编码实现-关键代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// 坐标转换
var getRectWH = function (mainmap, minimap){
// 投影坐标系:以东为x轴正半轴,以北为y轴正半轴
// 屏幕坐标系:以right为x轴正半轴,以bottom为y轴正半轴
var x, y, w, h;

var mainExtend = mainmap.getView().calculateExtent(mainmap.getSize());
var topLeftPixelCoor = minimap.getPixelFromCoordinate(ol.extent.getTopLeft(mainExtend));
var rightBottomPiexlCoor = minimap.getPixelFromCoordinate(ol.extent.getBottomRight(mainExtend));

x = topLeftPixelCoor[0];
y = topLeftPixelCoor[1];
w = Math.abs(topLeftPixelCoor[0]- rightBottomPiexlCoor[0]);
h = Math.abs(topLeftPixelCoor[1] - rightBottomPiexlCoor[1]);

// 返回结果
return {
x: x,
y: y,
width: w,
height: h
};
};

// 元素拖动
const move = function(event) {
const coordinates = ovmap.getEventCoordinate(computeDesiredMousePosition(event));

overlay.setPosition(coordinates);
};

const endMoving = function(event) {
const coordinates = ovmap.getEventCoordinate(event);

scope.getMap().getView().setCenter(coordinates);

window.removeEventListener('mousemove', move);
window.removeEventListener('mouseup', endMoving);
};

/* Binding */

overlayBox.addEventListener('mousedown', function() {
window.addEventListener('mousemove', move);
window.addEventListener('mouseup', endMoving);
});

总结和展望

鹰眼的实现涉及了最基本的坐标转换和坐标系的理解,只有理解 GIS 中屏幕坐标与地图坐标间的关系,才能实现这个功能。

参考