KCGIS平台结合 Leaflet,SVG结合解决地铁拓扑网络展现
项目需求
展现成都市地铁拓扑网络,要求要美观,性能要求高;美观方面,要求连线要平滑,地图缩放的时候没有延迟情况;要求支持10万也上的用户访问;客户端有web浏览器端,手机端等;用户点击站点可以看见站点的信息,拥挤成都等信息;地铁采用双线的方式显示,使用颜色表示该路段的拥挤程度;
思考
- 考虑到成都市地铁数据不大,可以通过离线下载到客户端的方式实现,这样可以解决地图大量用户访问的问题;这样就排除了使用动态地图等方案;
- 由于用户要求的是拓扑网络,所以数据应该是逻辑的,不是实际的;这个可以参考地铁上的车站图;连线要采用B样条曲线连接;
- 地图缩放的时候,需要重绘数据,可能会出现一个短暂的停顿情况,如下视频1所示;可以采用webgl/canvas/svg三种方式来解决,他们各自的优缺点可以在互联网上找到;我这里地铁的底图是不变的,我采用的是svg文件的方式绘制,逻辑网络在后台完成;拥堵情况采用webgl来绘制;
- 点击站点,通过气泡的方式显示站点的信息;这个需要在gis中有对应的要素,可以采用一个透明的图片的方式来实现;
实现
后台的工作需要通过KCGIS 地图平台生成逻辑点生成拓扑网络;
- 从用户哪里获取到所有站点的信息,连接关系等信息;通过arcmap等工具进行数据加工;当我们用到拐点的时候需要采用B样条插值计算;箭头所示的位置是一个隐藏的点,这个点是用于计算B样条.
- 我们可以直接指定拓扑连接关系,录入天府广场是1号线和2号线的交叉口
- 文字标注的位置,要通过用户指定的方式显示,一般分为在站点的上部,下部,左边,右边显示,如果发现有重叠,可以换一个位置显示;一般一条显示的站点,可以交叉的显示,例如前面一个在上面,后面一个就换成下面显示;
- 地图查询这些功能,使用leaflet来加载SVG数据和空间数据;
- 这块需要考虑一个坐标匹配的问题,需要在后台处理好;
- 考虑后续要对每条线路进行图层控制显示,所以每条线路为一个图层
**
前端实现
**
var map = L.map('map', { crs: L.CRS.EPSG3857 });
var myRenderer = L.svg({ padding: 0.5 });
var bounds = [[0, 0], [14.94, 20.00]];
function distance(x1, y1, x2, y2) {
var calX = Math.abs(x2 - x1);
var calY = Math.abs(y2 - y1);
var d = Math.sqrt( calX * calX + calY * calY );
return d;
}
function querySub(e)
{
var text = "";
var d = 100;
var name = "";
var x = e.latlng.lng;
var y = e.latlng.lat;
for(var i=0;i<points.length;i++)
{
var x1 = points[i].geometry.coordinates[0];
var y1 = points[i].geometry.coordinates[1];
var dd = distance(x, y, x1, y1);
if (dd <d)
{
d = dd;
name = points[i].properties.name;
}
}
if (d < 0.15) {
var popup = L.popup()
.setLatLng(e.latlng)
.setContent('当前站点是:' + name)
.openOn(map);
}
}
//每条线路为一个svg图层
var image0 = L.imageOverlay('subline0.svg', bounds, { opacity: 1, interactive: true }).on("click", querySub).addTo(map);
var image1 = L.imageOverlay('subline1.svg', bounds, { opacity: 1, interactive: true }).on("click", querySub).addTo(map);
var image2 = L.imageOverlay('subline2.svg', bounds, { opacity: 1, interactive: true }).on("click", querySub).addTo(map);
var image3 = L.imageOverlay('subline3.svg', bounds, { opacity: 1, interactive: true }).on("click", querySub).addTo(map);
var image4 = L.imageOverlay('subline4.svg', bounds, { opacity: 1, interactive: true }).on("click", querySub).addTo(map);
var image5 = L.imageOverlay('subline5.svg', bounds, { opacity: 1, interactive: true }).on("click", querySub).addTo(map);
var image6 = L.imageOverlay('subline6.svg', bounds, { opacity:1, interactive: true }).on("click", querySub).addTo(map);
map.fitBounds(bounds);
var mark8 = {
radius: 4,
fillColor: "#fff",
color: "#000",
weight: 1,
opacity: 1,
fillOpacity: 1
};
var mark4 = {
radius: 4,
fillColor: "#fff",
color: "#000",
weight: 1,
opacity: 1,
fillOpacity: 1,
labelAnchor: [4, -4]
};
function pointToLayer(feature, latlng) {
var mark = L.circleMarker(latlng, mark4);
if (feature.properties.t != null && feature.properties.t == 8)
mark = L.circleMarker(latlng, mark8);
return mark;
};
实现效果
效果地址:
http://demo.cd-kc.com:8000/cdsubway/web/index2.html
http://demo.cd-kc.com:8000/cdsubway/web/index.html
更多信息请关注kcgis平台
联系方式:
QQ:823007509
网址:http://www.cd-kc.cn