进行图形可视化,不免会遇到地理数据的可视化需求。一般状况下,直接使用echarts对配置项进行处理,就能够知足大部分需求。固然,更加复杂的定制化需求,可能就须要借助d三、Three.js等工具。若是对详细的地图背景有要求的话,又须要将图形库与leaflet、maptalks等地图引擎相结合。
不过也许你的需求和我同样,没有那么复杂的交互需求,但对显示效果却有一些想法。那么就能够尝试阅读本文,使用一种比较偷懒的方法,仅基于maptalks自己,来绘制可交互的伪3d地图。
下面,以贵州省的伪3d地图为例,进行代码的编写和相应数据的简单处理。
1.基本的地图绘制
maptalks(maptalks的git)的官方范例写得至关亲切,咱们能够从中找到全部绘制伪3d地图须要的元素。
首先,从地图底图开始。(官方入门示例)css
initMapTalk() { let map = new maptalks.Map('mapDom', { center: [121.345, 31.2088], zoom: 9, baseLayer: new maptalks.TileLayer('base', { urlTemplate: 'http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', subdomains: ['a','b','c','d'], attribution: '© <a href="http://osm.org">OpenStreetMap</a> contributors, © <a href="https://carto.com/">CARTO</a>' }) }); }
须要注意的是,除了maptalks.js之外,maptalks.css也是必须引入的。git
而后,咱们须要借助maptalks.Polygon添加一些地图区块(Polygon示例)。虽然地图看起来和长方体不太同样,实际上这些区块也不过是稍微复杂一些的点线集合而已。做为一切绘制的基础,咱们须要找一些GeoJson格式的数据(中国各省市级json,世界主要国家json)。观察GeoJson,其中,的coordinates属性,就是地图边界的集合。须要注意的是,区域type包含Polygon和MultiPolygon两类,和maptalks的多边形函数相对应,在数组的层级上稍有区别。为了减小数据选取的麻烦,这里选择使用MultiPolygon来进行绘制。github
drawPolygons(idx, coordinates, properties) { const polygon = new maptalks.MultiPolygon(coordinates, { symbol: { lineWidth: 1, lineColor: edgeColor, polygonFill: polygonColors[0], polygonOpacity: 0.5 }, properties: { id: properties.id, index: idx, properties: properties } }) .on("mouseenter", function(e) { e.target.updateSymbol({ polygonFill: polygonColors[1] }); }) .on("mouseout", function(e) { e.target.updateSymbol({ polygonFill: polygonColors[0] }); }) this.polygons.push(polygon); }, drawRegion() { const self = this $.getJSON("guizhou.json", "", function(mapData) { const features = mapData.features; features.forEach((g, i) => { const properties = g.properties; const coordinates = g.geometry.coordinates self.drawPolygons(i, coordinates, properties) }); const polygonsLayer = new maptalks.VectorLayer( "vector-polygon", self.polygons, ).addTo(self.mapDom); }) },
到如今为止,一切还只是2d的样子。不过,maptalks容许咱们绘制3维的高度面(立体的线)。只须要引入一个altitude属性,并在底图上引入pitch属性使视角稍稍偏移, 咱们的2.5d地图就画出来了。json
drawLimitLines(idx, coordinates, properties) { const outLine = new maptalks.MultiLineString(coordinates, { symbol: { lineColor: edgeColor, lineWidth: 1, textPlacement: "vertex" }, properties: { altitude: altitude, index: idx, id: properties.id, properties: properties } }); this.limitLines.push(outLine); }, drawPolygons(idx, coordinates, properties) { const polygon = new maptalks.MultiPolygon(coordinates, { symbol: { lineWidth: 1, lineColor: edgeColor, polygonFill: polygonColors[0], polygonOpacity: 0.5 }, properties: { altitude: altitude, id: properties.id, index: idx, properties: properties } }) .on("mouseenter", function(e) { e.target.updateSymbol({ polygonFill: polygonColors[1] }); }) .on("mouseout", function(e) { e.target.updateSymbol({ polygonFill: polygonColors[0] }); }) this.polygons.push(polygon); }, drawRegion() { const self = this $.getJSON("guizhou.json", "", function(mapData) { const features = mapData.features; features.forEach((g, i) => { const properties = g.properties; const coordinates = g.geometry.coordinates self.drawPolygons(i, coordinates, properties) const pathCoordinates = g.geometry.type == "MultiPolygon" ? coordinates.map(d => { return d[0] }) : coordinates self.drawLimitLines(i, pathCoordinates, properties) }); const polygonsLayer = new maptalks.VectorLayer( "vector-polygon", self.polygons, { enableAltitude: true } ).addTo(self.mapDom); const limitLinesLayer = new maptalks.VectorLayer( "vector-line", self.limitLines, { enableAltitude: true, drawAltitude: { polygonFill: edgeColor, polygonOpacity: 0.3, lineWidth: 0 } } ).addTo(self.mapDom); }) },
2.数据和样式处理
到这个时候,效果仍是不太使人满意。县市间的边界太丑,有没有什么办法把他去掉呢?很简单,直接绘制地图的外沿就好。不过,网上下载的贵州省边界好像和如今带有区县划分的精度不太同样?那么,就来本身处理一下吧。根据问答如何合并区域边界,访问在线的地图数据处理网站http://mapshaper.org/,给每一个县市取一个相同的别名,一番输入输出,咱们就获得了贵州省的外边界。segmentfault
drawBorderLines(coordinates, properties) { const outLine = new maptalks.MultiLineString(coordinates, { symbol: { lineColor: edgeColor, lineWidth: 1, textPlacement: "vertex" }, properties: { altitude: altitude, id: properties.id, properties: properties } }); this.limitLines.push(outLine); }, drawWall() { const self = this $.getJSON("guizhou-border.json", "", function(borderMapData) { const borderFeatures = borderMapData.features[0] const properties = borderFeatures.properties; const pathCoordinates = borderFeatures.geometry.coordinates.map(d => { return d[0] }) self.drawBorderLines(pathCoordinates, properties) const limitLinesLayer = new maptalks.VectorLayer( "vector-line", self.limitLines, { enableAltitude: true, drawAltitude: { polygonFill: edgeColor, polygonOpacity: 0.3, lineWidth: 0 } } ).addTo(self.mapDom); }) }
固然,mapshaper的功效不止于此,简直是区域数据处理的一大利器,很是值得探索。
另外一个使人不太满意的是地图的底图。打开mapbox,找到Studio而后Start With Basic,一个全新的自配地图的世界等待着你。这里,就随便先把英文的区县名换成中文好了。
完成配置以后,点击share,你会获得一个连接。不过,在用他替换掉Map的urlTemplate以前,还要按照格式进行一下修整。
最后,就获得了本文开头所示的地图。相关源码数组