進行圖形可視化,不免會遇到地理數據的可視化需求。一般狀況下,直接使用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以前,還要按照格式進行一下修整。
最後,就獲得了本文開頭所示的地圖。相關源碼數組