這次我們準備利用D3畫一個中國地柒爵。
lib版本
https://d3js.org/d3.v4.min.js
https://d3js.org/topojson.v2.min.js
如下圖:
一. 目前中國地圖的地理文件格式有兩種芙粱,GeoJSON和TopoJSON。
GeoJSON
GeoJSON 是用于描述地理空間信息的數(shù)據(jù)格式己肮。GeoJSON 不是一種新的格式,其語法規(guī)范是符合 JSON 格式的,只不過對其名稱進行了規(guī)范洪鸭,專門用于表示地理信息挡毅。
GeoJSON 的最外層是一個單獨的對象(object)蒜撮。這個對象可表示:
- 幾何體(Geometry)
- 特征(Feature)
- 特征集合(FeatureCollection)
最外層的 GeoJSON 里可能包含有很多子對象,每一個 GeoJSON 對象都有一個 type 屬性跪呈,表示對象的類型段磨,type 的值必須是下面之一。- Point:點耗绿。
- MultiPoint:多點薇溃。
- LineString:線。
- MultiLineString:多線缭乘。
- Polygon:面沐序。
- MultiPolygon:多面琉用。
- GeometryCollection:幾何體集合。
- Feature:特征策幼。
- FeatureCollection:特征集合邑时。
如下面代碼
點對象:
{
"type": "Point",
"coordinates": [ -135, 39 ]
}
線對象:
{
"type": "LineString",
"coordinates": [[-135, 39 ], [-137, 38 ]]
}
面對象:
{
"type": "Polygon",
"coordinates":[[ [30, 0], [31, 0], [31, 5], [30, 5], [30, 0] ]]
}
由以上格式可以發(fā)現(xiàn),每一個對象都有一個成員變量 coordinates特姐。如果 type 的值為 Point晶丘、MultiPoint、LineString唐含、MultiLineString浅浮、Polygon、MultiPolygon 之一捷枯,則該對象必須有變量 coordinates滚秩。
如果 type 的值為 GeometryCollection(幾何體集合),那么該對象必須有變量 geometries淮捆,其值是一個數(shù)組郁油,數(shù)組的每一項都是一個 GeoJSON 的幾何對象。例如:
{
"type": "GeometryCollection",
"geometries": [
{
"type": "Point",
"coordinates": [100, 40]
},
{
"type": "LineString",
"coordinates": [ [100, 30], [100, 35] ]
}
]
}
如果 type 的值為 Feature(特征)攀痊,那么此特征對象必須包含有變量 geometry桐腌,表示幾何體,geometry 的值必須是幾何體對象苟径。此特征對象還包含有一個 properties案站,表示特性,properties 的值可以是任意 JSON 對象或 null棘街。例如:
{
"type": "Feature",
"properties": {
"name": "北京"
},
"geometry": {
"type": "Point",
"coordinates": [ 116.3671875, 39.977120098439634]
}
}
如果 type 的值為 FeatureCollection(特征集合)嚼吞,則該對象必須有一個名稱為 features 的成員。features 的值是一個數(shù)組蹬碧,數(shù)組的每一項都是一個特征對象舱禽。
TopoJSON
TopoJSON 是 GeoJSON 按拓撲學編碼后的擴展形式,是由 D3 的作者 Mike Bostock 制定的恩沽。相比 GeoJSON 直接使用 Polygon誊稚、Point 之類的幾何體來表示圖形的方法,TopoJSON 中的每一個幾何體都是通過將共享邊(被稱為arcs)整合后組成的罗心。
TopoJSON 消除了冗余里伯,文件大小縮小了 80%,因為:
- 邊界線只記錄一次(例如廣西和廣東的交界線只記錄一次)渤闷。
- 地理坐標使用整數(shù)疾瓮,不使用浮點數(shù)。
引用來自ourd3js.com
二. 準備D3JS飒箭, 構(gòu)建最簡單的中國地圖
上面已經(jīng)說過了狼电,地理的JSON文件分為TopoJSON 和GeoJSON, 現(xiàn)在我們使用TopoJSON來完成接下來的構(gòu)建蜒灰。
- 在項目中引入兩個lib
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
- 生成投影 和投影相對于的路徑生成器
#生成路徑生成器
generatePath(scale) {
let self = this;
var projection = self.generateProjection(scale);
return d3.geoPath().projection(projection);
},
#生成投影
generateProjection(scale) {
var svg = d3.select("svg"),
width = svg.attr("width"),
height = svg.attr("height");
return d3.geoMercator()
.center([105, 31])
.scale(scale)
.translate([width / 2, height / 2 + height / 6])
},
- 獲取中國地圖數(shù)據(jù)
initChinaMap() {
let self = this;
var path = self.generatePath(950);
var pathCubier = self.generatePath(958);
var color = function(i) {
return d3.color('#02005A');
};
var svg = d3.select("svg");
d3.json("/static/js/china-topo.json", function(error, root) {
if (error)
return console.error(error);
//畫陰影背景
svg.append("g")
.attr("filter", "url(#f1)")
.attr("fill", "rgba(45,107,253,1)")
.attr('style', 'border: 1px solid #fff;')
.selectAll("path")
.data(topojson.feature(root, root.objects.china).features)
.enter()
.append("path")
.attr("stroke", "rgba(45,107,253,1)")
.attr("stroke-width", 1)
.attr("fill", "rgba(45,107,253,1)")
.attr("d", pathCubier)
.select('circle')
.data(topojson.feature(root, root.objects.china).features)
.enter()
.append("circle")
.attr('cx', '0')
.attr('cy', '0')
.attr('r', 500)
.attr('fill', 'transparent')
//畫立體層級感
svg.append("g")
.attr("fill", "#59acc8")
.selectAll("path")
.data(topojson.feature(root, root.objects.china).features)
.enter()
.append("path")
.attr("stroke", "#59acc8")
.attr("stroke-width", 1)
.attr("fill", "#59acc8")
.attr("d", pathCubier)
//畫中國地圖
svg.append("g")
.attr("fill", "#02005A")
.selectAll("path")
.data(topojson.feature(root, root.objects.china).features)
.enter()
.append("path")
.attr("stroke", "#1C98C8")
.attr("stroke-width", 1)
.attr("fill", function(d, i) {
return color(i);
})
.attr("d", path)
.append("title")
.text(function(d) {
// console.log("d", d)
return d.properties.name;
})
});
},
這里為了畫出地圖的立體效果和陰影效果, 將整個地圖分成了 三部分肩碟,强窖,先畫陰影部分
再畫立體部分
最后畫地圖具體的輪廓
最后,按照順序合再一起就可以畫出削祈,有陰影翅溺,有立體的中國地圖。
有任何問題髓抑,可以聯(lián)系我
email: cheng_cong123@163.com
當然咙崎,這個立體感是有問題的,有誰知道是什么問題嗎吨拍?可以留言褪猛!