推薦技術(shù)棧
amap + g2/ amap + L7
mapbox + deck.gl/echarts.gl
地理相關(guān)庫
amap
mapbox
Leaflet
Cesium
deck.gl
g2 map類
turfjs
工具
http:///#map=2/20.0...
地圖選擇器
地圖3D
https:///AlexZ33/pe...點擊預(yù)覽
https:///AlexZ33/pe...點擊預(yù)覽
北京市居住人口3D分布
https://github.com/zhu18/visualcontrols
樓宇
https:///AlexZ33/pe...點擊預(yù)覽 用css實現(xiàn)太累
城市統(tǒng)計
上海城市統(tǒng)計
圖層
Mapv - 地理信息可視化開源庫
https://github.com/chengquan2...
高德地圖api
百度地圖api
http://lbsyun.baidu.com/index...
http://mapv.baidu.com/gallery...
vue-baidu-map
注意
百度地圖webapi接口文檔
百度地圖javascript api文檔
使用百度地圖的服務(wù),需使用BD09坐標(biāo)。
若使用非BD09坐標(biāo)、未經(jīng)過坐標(biāo)轉(zhuǎn)換(非BD09轉(zhuǎn)成BD09)直接疊加在地圖上,地圖展示位置會偏移,因此通過其他坐標(biāo)(WGS84、GCJ02)調(diào)用服務(wù)時,需先將其他坐標(biāo)轉(zhuǎn)換為BD09。
非百度坐標(biāo)系,如何轉(zhuǎn)換成百度坐標(biāo)系?
http://lbsyun.baidu.com/index...
http://lbsyun.baidu.com/index...
圖吧地圖api
Mapbox api
地圖API和工具
坐標(biāo)拾取器械
https:///AlexZ33/pe...點擊預(yù)覽
另外,百度地圖api的開發(fā)文檔下的工具支持中有很多類似的工具
Vue Baidu Map
地圖選擇器
GeoJSON
turf.js
坐標(biāo)系統(tǒng)說明
高德地圖: GCJ-02 我國地圖坐標(biāo)系統(tǒng)
百度地圖: BD-09 (BD-09II/bd09mc)
普通GPS定位出來的數(shù)值都是基于WSG-84坐標(biāo)系標(biāo)準,這是世界通用的坐標(biāo)系。(美國的)
GCJ-02和WSG-84之間的坐標(biāo)系轉(zhuǎn)換算法是保密的。
“中國政府為了國家安全在國內(nèi) GPS 定位時人為加入一定偏移”這種說法是不正確的。
應(yīng)該是“我國所發(fā)行的地圖類產(chǎn)品強制性加入偏移算法,使原本標(biāo)準的坐標(biāo)系統(tǒng)(WSG-84)變?yōu)閲冶C艿淖远x坐標(biāo)系統(tǒng)(GCJ-02)”。
坐標(biāo)系說明
在進行地圖開發(fā)過程中,我們一般能接觸到以下三種類型的地圖坐標(biāo)系:
1.WGS-84原始坐標(biāo)系,一般用國際GPS紀錄儀記錄下來的經(jīng)緯度,通過GPS定位拿到的原始經(jīng)緯度,Google和高德地圖定位的的經(jīng)緯度(國外)都是基于WGS-84坐標(biāo)系的;但是在國內(nèi)是不允許直接用WGS84坐標(biāo)系標(biāo)注的,必須經(jīng)過加密后才能使用;
2.GCJ-02坐標(biāo)系,又名“火星坐標(biāo)系”,是我國國測局獨創(chuàng)的坐標(biāo)體系,由WGS-84加密而成,在國內(nèi),必須至少使用GCJ-02坐標(biāo)系,或者使用在GCJ-02加密后再進行加密的坐標(biāo)系,如百度坐標(biāo)系。高德和Google在國內(nèi)都是使用GCJ-02坐標(biāo)系,可以說,GCJ-02是國內(nèi)最廣泛使用的坐標(biāo)系;
3.百度坐標(biāo)系:bd-09,百度坐標(biāo)系是在GCJ-02坐標(biāo)系的基礎(chǔ)上再次加密偏移后形成的坐標(biāo)系,只適用于百度地圖。(目前百度API提供了從其它坐標(biāo)系轉(zhuǎn)換為百度坐標(biāo)系的API,但卻沒有從百度坐標(biāo)系轉(zhuǎn)為其他坐標(biāo)系的API)
three.js地圖
http://blog.csdn.net/u0125393...
Three.js - 用100行javascript代碼創(chuàng)建一座城市
https://github.com/doter1995/earthquakes
G2地圖
地圖數(shù)據(jù)
通常情況下,地理數(shù)據(jù)的可視化會包含多份數(shù)據(jù):一份是用于繪制地圖的經(jīng)緯度數(shù)據(jù),一份是用戶真正想要可視化的用戶數(shù)據(jù)。
實例 中國地圖-省市下鉆只有經(jīng)緯度數(shù)據(jù),但是特殊的是,這個實例中,我們從amap api獲得數(shù)據(jù),在左側(cè)繪制地圖(其中中國地圖直接得到的geoJSON數(shù)據(jù),行政區(qū)劃得到的是TopoJSON數(shù)據(jù)),在右側(cè)用g2繪制處理行政區(qū)劃數(shù)據(jù)(geojson -> json數(shù)組 --> dataset) 繪制地圖
實例 帶氣泡的地圖 需要在世界地圖上標(biāo)注各個國家的男女比例情況,這個時候就可以使用多視圖的可視化方案:詳情 戳 --->這
地圖數(shù)據(jù)一般保存為JSON格式,G2和D3常用的有兩種:
GeoJSON 描述地理信息的一種基本格式 例——> world.geo.json
TopoJSOND3作者Mike Bostock制定的格式,符合JSON規(guī)范
我們以這個g2 中國地圖-省市下鉆為例
g2/demos/map-drill-down.html
<!doctype html><html lang="en"><head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>中國地圖-省市下鉆</title>
<link rel="stylesheet" />
<style>
.button-group{ position: fixed; bottom:50%; left: 0px; width: 70%;
} </style>
<script type="text/javascript" src="http://cache.amap.com/lbs/static/addToolbar.js"></script></head><body>
<div id="mountNode"></div>
<div class='button-group' style="background-color: #fff">
<input type='radio' onclick='refresh(this.value)' checked name='mapStyle' value='normal'>標(biāo)準 <input type='radio' onclick='refresh(this.value)' name='mapStyle' value='dark'>幻影黑 <input type='radio' onclick='refresh(this.value)' name='mapStyle' value='light'>月光銀 <input type='radio' onclick='refresh(this.value)' name='mapStyle' value='fresh'>草色青 <input type='radio' onclick='refresh(this.value)' name='mapStyle' value='grey'>雅士灰<br>
<input type='radio' onclick='refresh(this.value)' name='mapStyle' value='graffiti'>涂鴉 <input type='radio' onclick='refresh(this.value)' name='mapStyle' value='whitesmoke'>遠山黛 <input type='radio' onclick='refresh(this.value)' name='mapStyle' value='macaron'>馬卡龍 <input type='radio' onclick='refresh(this.value)' name='mapStyle' value='blue'>靛青藍 <input type='radio' onclick='refresh(this.value)' name='mapStyle' value='darkblue'>極夜藍<br>
<input type='radio' onclick='refresh(this.value)' name='mapStyle' value='wine'>醬籽 </div>
<script>/*Fixing iframe window.innerHeight 0 issue in Safari*/document.body.clientHeight;</script>
<script src="https://gw./os/antv/assets/g2/3.0.4-beta.2/g2.min.js"></script>
<script src="https://gw./os/antv/assets/data-set/0.8.3/data-set.min.js"></script>
<script src="https://gw./os/antv/assets/lib/jquery-3.2.1.min.js"></script>
<script src="https://gw./os/antv/assets/lib/lodash-4.17.4.min.js"></script>
<script src="https://webapi.amap.com/maps?v=1.4.1&key=8c8c021990b332b22254f2f8289a62ef"></script>
<script src="https://webapi.amap.com/ui/1.0/main.js?v=1.0.11"></script>
<script>
$('#mountNode').html( '<div style="position:relative;">'+ '<div id="china" style="width:50%;height:400px;position:absolute;left:0;top:0"></div>' + '<div id="province" style="width:50%;height:400px;position:absolute;right:0;top:0;"></div>'+ '</div>'
); //調(diào)用高德api繪制底圖以及geo數(shù)據(jù)
const map = new AMap.Map('china',{ resizeEnable: true, zoom:4
}); function refresh(enName) {
map.setMapStyle('amap://styles/'+enName);
} const colors = [ "#3366cc", "#dc3912", "#ff9900", "#109618", "#990099", "#0099c6", "#dd4477", "#66aa00", "#b82e2e", "#316395", "#994499", "#22aa99", "#aaaa11", "#6633cc", "#e67300", "#8b0707", "#651067", "#329262", "#5574a6", "#3b3eac" ]; // 當(dāng)前聚焦的區(qū)域
let currentAreaNode;
AMapUI.load(['ui/geo/DistrictExplorer', 'lib/$'], function(DistrictExplorer) { //創(chuàng)建一個實例
const districtExplorer = window.districtExplorer = new DistrictExplorer({ eventSupport: true, //打開事件支持
map
});// //創(chuàng)建一個輔助Marker,提示鼠標(biāo)內(nèi)容// var tipMarker = new AMap.Marker({// //啟用冒泡,否則click事件會被marker自己攔截// bubble:true// });//
// feature 被點擊
districtExplorer.on('featureClick', function(e, feature) { const props = feature.properties; //如果存在子節(jié)點
console.log(props); if(props.childrenNum > 0) { //切換聚焦區(qū)域
switch2AreaNode(props.adcode);
}
}); //外部區(qū)域被點擊
districtExplorer.on('outsideClick', function(e) {
districtExplorer.locatePosition(e.originalEvent.lnglat, function(error,routeFeatures) { if(routeFeatures && routeFeatures.length > 1) { //切換到省級區(qū)域
switch2AreaNode(routeFeatures[1].properties.adcode);
}else{ //切換到全國
switch2AreaNode(100000)
}
},{ levelLimit:2
});
}); //繪制某個區(qū)域的邊界
function renderAreaPolygons(areaNode) { const node = _.cloneDeep(areaNode);
districtExplorer.clearFeaturePolygons();
districtExplorer.renderSubFeatures(node, function(feature, i) { const fillColor = colors[i % colors.length]; const strokeColor = colors[colors.length - 1 -i % colors.length]; return { cursor: 'default', bubble:true,
strokeColor,//線顏色
strokeOpacity:1,//線透明度
strokeWeight:1, //線寬
fillOpacity: 0.35 //填充透明度
};
}); //繪制父區(qū)域
districtExplorer.renderParentFeature(node, { cursor: 'default', bubble: true, strokeColor: 'black',//線顏色
strokeOpacity: 1, //線透明度
strokeWeight: 1, //線寬
fillColor: null, //填充色
fillOpacity: 0.35 //填充透明度
});
} //切換區(qū)域后刷新顯示內(nèi)容
function refreshAreaNode(areaNode) {
districtExplorer.setHoverFeature(null);
renderAreaPolygons(areaNode)
} //切換區(qū)域
function switch2AreaNode(adcode, callback) { if (currentAreaNode && ('' + currentAreaNode.getAdcode() === '' + adcode)) { return;
}
loadAreaNode(adcode, function(error, areaNode) { if (error) { if (callback) {
callback(error);
} return;
}
currentAreaNode = window.currentAreaNode = areaNode;
refreshAreaNode(areaNode); if (callback) {
callback(null, areaNode);
}
});
} //加載區(qū)域
function loadAreaNode(adcode, callback) {
districtExplorer.loadAreaNode(adcode, function(error, areaNode) { if(error) { if(callback) {
callback(error);
} return;
}
renderG2Map(areaNode); //使用 G2 繪制地圖
if(callback) {
callback(null, areaNode);
}
});
} //浙江
switch2AreaNode(330000);
}); //開始使用G2繪制地圖
let provinceChart; function renderG2Map(areaNode) { const adcode = areaNode.getAdcode(); const geoJSON = areaNode.getSubFeatures(); // 獲取 geoJSON 數(shù)據(jù)
const name = areaNode.getName();
provinceChart && provinceChart.destroy();
provinceChart = null; if (!geoJSON || currentAreaNode && ('' + currentAreaNode.getAdcode() === '' + adcode)) { return;
} const dv = processData(geoJSON); // start: 計算地圖的最佳寬高
const longitudeRange = dv.range('longitude'); const lantitudeRange = dv.range('lantitude'); const ratio = (longitudeRange[1] - longitudeRange[0]) / (lantitudeRange[1] - lantitudeRange[0]); let width; let height; if (ratio > 1) {
width = $('#province').width();
height = width / ratio;
} else {
width = 300 * ratio;
height = $('#province').height();
} // end: 計算地圖的最佳寬高
provinceChart = new G2.Chart({ container: 'province',
width,
height, padding: 0
});
provinceChart.source(dv);
provinceChart.axis(false);
provinceChart.tooltip({ showTitle: false
});
provinceChart
.polygon()
.position('longitude*lantitude')
.label('name', { textStyle: { fill: '#fff', fontSize: 10, shadowBlur: 2, shadowColor: 'rgba(0, 0, 0, .45)'
}
})
.style({ stroke: '#fff', lineWidth: 1
})
.color('value', '#BAE7FF-#1890FF-#0050B3');
provinceChart.guide().text({ position: [ 'min', 'max' ], offsetY: 20, content: name, style: { fontSize: 14, fontWeight: 'bold'
}
});
provinceChart.render();
} function processData(geoJSON) { console.log("---------------------geoJSON---------------------------"); console.log(geoJSON); const mapData = { type: 'FeatureCollection', features: geoJSON
}; // 構(gòu)造虛擬數(shù)據(jù)
const userData = []; for (let i = 0; i < geoJSON.length; i++) { const name = geoJSON[i].properties.name;
userData.push({
name, value: Math.round(Math.random() * 1000)
});
} console.log("----------------userData----------------"); console.log(userData); const ds = new DataSet(); const geoDataView = ds.createView().source(mapData, { type: 'GeoJSON'
}); // geoJSON 經(jīng)緯度數(shù)據(jù)
// 用戶數(shù)據(jù)
const dvData = ds.createView().source(userData);
dvData.transform({ type: 'geo.region', field: 'name',
geoDataView, as: [ 'longitude', 'lantitude' ]
}); console.log('---------------------dvData-------------'); console.log(dvData); return dvData;
} </script></body></html>這里的代碼
AMapUI.load(['ui/geo/DistrictExplorer', 'lib/$'], function(DistrictExplorer) {
}是對高德地圖ui的組件調(diào)用,DistrictExplorer是行政區(qū)劃瀏覽
自有組件還有:參考組件 UI組件庫
我們還可以自定義組件模塊,AMapUI組件庫的擴展 ,詳情戳這里————> AMapUI組件庫高級功能
ui/geo/DistrictExplorer是擴展的模塊路徑
lib/$, 即DomLibrary(jQuery或者Zepto)
這里load的json數(shù)據(jù)是這樣的,其中的topo內(nèi)的就是TopoJSON數(shù)據(jù)
geo/DistrictExplorer.json
type 是Topology,表示文件類型
transform用于描述縮放量和平移量,分別用一個只有兩項的數(shù)組來表示
objects里存有幾何體模塊,此處只有浙江省parent 是全省sub 是各市縣arcs表示如何從最外層的數(shù)組arcs里提取地形.
注意 :
相比GeoJSON直接使用Polygon、Point之類的幾何體來表示圖形的方法,TopoJSON中的每一個幾何體都是通過將共享邊(被稱為arcs)整合后組成
TopoJSON消除了冗余,文件大小縮小了80%,因為:
邊界線只記錄一次
地理坐標(biāo)使用整數(shù),不使用浮點數(shù)
地圖投影
我們再看一看 g2的另一個實例 : 帶氣泡的地圖
const dv = ds.createView('back')
.source(mapData,{ type: 'GeoJSON'
})
.transform({ type:'geo.projection',
projection: 'geoMercator', as:['x','y','centroidX','centroidY']
});這里的 projection: 'geoMecator',表示投影是墨卡托投影
墨卡托投影、高斯-克呂格投影、UTM投影
我們可以看看d3里面關(guān)于地圖的投影api,看看有哪些地圖投影:
d3.js Azimuthal Projections
繪制過程
相比2.0版本 3.0版本的container是支持string 也支持dom對象的
從上面兩個例子我們可以看出來,在載入地圖時候我們可以
調(diào)用amap api地圖
本地GeoJSON或TopoJSON生成
這里我們說一說如何載入數(shù)據(jù)
如何裝載數(shù)據(jù)
這里我們可以看到 g2中繪制地圖時候需要 傳入一個JSON數(shù)組
所以上面例子中國地圖-省市下鉆 的 const dv = processData(geoJSON); processData函數(shù)應(yīng)該有這樣一個轉(zhuǎn)換過程 GeoJSON --> JSON數(shù)組 --> DataSet,我們來看一看是不是這樣(即userData應(yīng)該是JSON數(shù)組,dvData應(yīng)該是DataSet)
const geoDataView = ds.createView().source(mapData, { type: 'GeoJSON'
}); // geoJSON 經(jīng)緯度數(shù)據(jù)為什么是轉(zhuǎn)換為Dataset?
自 G2 3.0 版本開始,原先內(nèi)置的數(shù)據(jù)處理模塊 frame 從 G2 包中抽離出來,獨立成為 DataSet 包。DataSet 的目標(biāo)是為數(shù)據(jù)可視化場景提供狀態(tài)驅(qū)動(state driven)的 -->DataSet
<script src="https://gw./os/antv/assets/data-set/0.8.1/data-set.js"></script>
在DataSet包中
我們把數(shù)據(jù)處理分為兩個大的步驟:數(shù)據(jù)連接(Connector)和數(shù)據(jù)轉(zhuǎn)換(Transform)。Connector 負責(zé)導(dǎo)入和歸一化數(shù)據(jù)(譬如導(dǎo)入 CSV 數(shù)據(jù),導(dǎo)入 GeoJSON 數(shù)據(jù)等),Transform 負責(zé)進行各種數(shù)據(jù)轉(zhuǎn)換操作(譬如圖布局、數(shù)據(jù)統(tǒng)計、數(shù)據(jù)補全等)。
想要了解G2中數(shù)據(jù)的處理流程直接點擊
常用實例
基于baidu、google、arcgis、高德地圖、canvas數(shù)據(jù)可視化
GeoHey gallery
文章
基于WebGL的大數(shù)據(jù)二三維可視化--uber的deck.gl介紹
deck.gl example
可視化篇:mapbox + echarts-gl 展示血脈交通
從Mapbox的開源工具看Web GIS的發(fā)展
ECharts 地圖博客
echarts結(jié)合高德API進行地圖下鉆
參考
一站式解決echarts實現(xiàn)區(qū)域地圖
Map Projection Overview
[python處理地理數(shù)據(jù)-geopandas和pyshp]()
mapbox/node-fontnik工具使用介紹
Mapbox GL JS本地化實踐
GIS文章集
Geomatics(GIS,GPS,RS,Surveying)
地圖應(yīng)用API(GIS+LBS)
antv g2的理解總結(jié)
Maps
inMap
https:///stevepeppl...
https:///AlexZ33/pe...點擊預(yù)覽
https:///pbeshai/pr...
https:///jakealbaug...
https://github.com/LylaYuKako...




