在地图可视化中的绘制中,实现地图要素的框选是十分常见的需求。下面就让我们来看看如何使用 antv/L7 快速实现上述的框选效果。
首先让我们来添加地图底图,为了实现框选的操作,我们先将地图的拖动设置关闭。
const scene = new Scene({
id: 'map',
map: new GaodeMap({
center: [ 110, 30 ],
zoom: 2.5,
style: 'dark',
dragEnable: false // 关闭地图拖动
})
});
然后让我们来绘制地图上显示的行政区划以及边框。
const chinaPolygonLayer = new PolygonLayer({
autoFit: true
})
.source(data)
.color("name", [
"rgb(239,243,255)",
"rgb(189,215,231)",
"rgb(107,174,214)",
"rgb(49,130,189)",
"rgb(8,81,156)"
])
.shape("fill");
// 图层边界
const chinaBorderLineLayer = new LineLayer({
zIndex: 2
})
.source(data)
.color("rgb(93,112,146)")
.size(0.6);
为了表示我们的框选操作以及我们的框选结果,我们使用两个单独的图层来表示。
const selectLineLayer = new LineLayer({ // 表示我们框选的结果
zIndex: 2
})
.source(emptyFeatureCollextion)
.color("#fff")
.size(2);
const boxLayer = new PolygonLayer({}) // 表示我们框选的操作
.source(emptyFeatureCollextion)
.color("#fff")
.size(2)
.style({
opacity: 0.6,
lineType: 'dash',
dashArray: [5, 5]
})
.shape("line");
为了实现实时的框选操作,我们需要监听场景的拖动事件(这也是我们先将地图的拖动关闭的原因)。antv/L7 默认就会将拖拽对应的事件抛出,我们只需要注册监听就可以了。
// 在拖拽开始的时候初始化计算相关的参数
scene.on("dragstart", (e) => {
selectLineLayer.setData(emptyFeatureCollextion);
startLngLat = {
...e.lngLat,
x: e.target.x,
y: e.target.y
};
});
// 在拖拽操作的时候我们需要实时更新选框(选框用于辅助,方便可视化操作)
scene.on('dragging',e => {
const {
lng: startLng,
lat: startLat
} = startLngLat;
const { lng: endLng, lat: endLat } = e.lngLat;
boxLayer.setData({
type: 'FeatureCollection',
features: [{
type: 'Feature',
properties: {},
geometry: {
type: 'Polygon',
coordinates: [[
[ startLng, endLat ],
[ endLng, endLat ],
[ endLng, startLat ],
[ startLng, startLat ],
[ startLng, endLat ]]]
}}]
});
});
// 在拖拽结束的时候计算本次拖拽操作选中的地图要素,同时更新线图层来表示我们当前选中的要素
scene.on('dragend', e => {
const {
x: startX,
y: startY
} = startLngLat;
const { x: endX, y: endY } = e.target;
boxLayer.setData(emptyFeatureCollextion);
const selectData = [ startX - left, startY - top, endX - left, endY - top ];
chinaPolygonLayer.boxSelect(getSelectData(selectData),
features => {
const currentSelectNames = features
.map(item => item.properties.name)
.join(',');
if (currentSelectNames !== selectNames) {
selectLineLayer.setData({
type: 'FeatureCollection',
features: [ ...features ]
});
}});
});
在上述操作中,核心代码只用一句,那就是调用 boxSelect 方法:
chinaPolygonLayer.boxSelect([startX, startY, endX, endY])
通过调用该方法,我们可以很方便的计算出当前框选范围内有哪些地图要素。大家感兴趣的话可以查看在线案例。
欢迎大家来 github 给 L7 提一提 issues!PR!Star! github.com/antvis/L7
欢迎大家搜索加入 L7 的钉钉答疑群:32292906