僅作閱讀理解API文檔時的參考,如有錯誤麻煩指正,多謝~
Map projections are sometimes implemented as point transformations.
地圖投影有時會由點轉(zhuǎn)換實現(xiàn)。
This is a reasonable mathematical approach if your geometry consists of continuous, infinite point sets. Yet computers do not have infinite memory, so we must instead work with discrete geometry such as polygons and polylines!
如果你的球面幾何由連續(xù)的無限點集合組成,這是一個合理的數(shù)學(xué)方法。 由于計算機沒有無限的內(nèi)存,因此我們必須使用離散的幾何圖形,如多邊形和折線!
Discrete geometry makes the challenge of projecting from the sphere to the plane much harder. The edges of a spherical polygon are geodesics (segments of great circles), not straight lines. Projected to the plane, geodesics are curves in all map projections except gnomonic, and thus accurate projection requires interpolation along each arc. D3 uses adaptive sampling inspired by a popular line simplification method to balance accuracy and performance.
使用離散的幾何圖形進行球面投影到平面是非常困難的。球形的多邊形的邊緣是測地線,而不是直線。投影到平面,測地線是所有地圖投影(除了點切投影)的曲線,因此準確的投影需要沿著每個弧線進行插值。D3使用自適應(yīng)采樣(受一種流行的線簡化方法而啟發(fā)得到的)方法來平衡精準度和性能。
The projection of polygons and polylines must also deal with the topological differences between the sphere and the plane. Some projections require cutting geometry that crosses the antimeridian, while others require clipping geometry to a great circle. Furthermore, spherical polygons require a winding order convention to determine which side of the polygon is the inside: D3 and TopoJSON use clockwise winding. (Spherical polygons can be larger than a hemisphere! See also ST_ForceRHR in PostGIS.)
多邊形和折線的投影還必須處理球體與平面之間的拓撲差異。一些投影需要穿過對向子午線切割球體,另一些投影需要將球體裁剪成一個大圓。此外,球形多邊形需要一個環(huán)繞的順序約定來決定多邊形的哪邊是內(nèi)側(cè):D3和TopoJSON采用的是順時針順序。(球面多邊形可以大于半球!另請參見PostGIS中的ST_ForceRHR。)
D3’s approach affords great expressiveness: you can choose the right projection, and the right aspect, for your data. D3 supports a wide variety of common and unusual map projections. For more, see Part 2 of The Toolmaker’s Guide.
D3提供了豐富的表現(xiàn)力:您可以為您的數(shù)據(jù)選擇正確的投影和正確的方面。D3提供多種常見和不常見的地圖投影。有關(guān)更多信息,請參閱 The Toolmarker's Guide的Part2 。
D3 uses GeoJSON to represent geographic features in JavaScript. (See also TopoJSON, an extension of GeoJSON that is significantly more compact and encodes topology.) To convert shapefiles to GeoJSON, use ogr2ogr, part of the GDAL package. In addition to map projections, D3 includes useful spherical shape generators and spherical math utilities.
D3使用GeoJSON來展示JavaScript中的地理要素。(另請參閱TopoJSON,它是GeoJSON的擴展,它大大的壓縮和編碼了拓撲布局。)要將shapefiles轉(zhuǎn)換為GeoJSON,請使用ogr2ogr,它是GDAL軟件包的一部分。 除了地圖投影,D3包括有用的球形生成器和球面數(shù)學(xué)實用工具。
安裝
<script src="https://d3js.org/d3-array.v1.min.js"></script>
<script src="https://d3js.org/d3-geo.v1.min.js"></script>
<script>
var projection = d3.geoAlbers(),
path = d3.geoPath(projection);
</script>
地圖數(shù)據(jù)
如何獲取中國地圖的 GeoJSON 文件呢,真的有點麻煩,可以參照: https://github.com/clemsos/d3-china-map 進行制作。
Mark
- 中國地圖的 GeoJSON 文件: china.geojson
- 各縣的JSON地圖文件:mapdata.zip
解壓縮后有兩個文件夾和一個 JSON 文件:
geometryCouties:各市~縣的數(shù)據(jù)
geometryProvince:各省~市的數(shù)據(jù)
china.json:中國~省的數(shù)據(jù) - 【 地圖系列 】 世界地圖和主要國家的 JSON 文件:
http://www.ourd3js.com/wordpress/668/
API
Paths
地理路徑生成器d3.geoPath類似于d3-shape中的形狀生成器:給定GeoJSON幾何結(jié)構(gòu)或特征對象,它生成SVG path數(shù)據(jù)字符串或渲染到Canvas的path。 動態(tài)或交互式投影中推薦使用Canvas,以提高性能。 Path數(shù)據(jù)可以在投影或變換一起使用,也可用于將平面幾何直接渲染成Canvas或SVG。
var path = d3.geoPath(projection); //創(chuàng)建一個新的地理路徑生成器。
path(object); //返回對象的路徑;
path.area(object) //計算給定要素的投影面積;
path.bounds(object) //計算給定要素的投影邊界。
path.centroid(object) //計算給定要素的投影中心。
path.context(context) //設(shè)置渲染上下文,可設(shè)置canvas的context。
path.context() //取得渲染上下文。
path.pointRadius(radius) //設(shè)置點要素的半徑。
path.pointRadius() //取得點要素的半徑。
path.projection(projection) //設(shè)置地理投影。
path.projection() //設(shè)置地理投影。
Projections(投影)
投影將球形多邊形轉(zhuǎn)換為平面多邊形。 D3提供了幾類標準投影的實現(xiàn):
var projection = d3.geoMercator();
projection(point) // 投影指定的位置,參數(shù)為經(jīng)緯度[longitude,latitude],獲得指定位置的坐標[x,y]。
projection.invert(point) // 為指定的位置反轉(zhuǎn)投影,參數(shù)為[x,y],獲得指定坐標的經(jīng)緯度[longitude,latitude]。
projection.stream(stream) // 包裝指定的流監(jiān)聽器,投影輸入的幾何圖形。
projection.clipAngle(angle) //設(shè)置投影的裁剪圓半徑,指定角度并返回投影。如果角度為null,切換到子午線切割,而不是小圈的裁剪。
projection.clipAngle() //返回當前裁剪的角度,默認為空。小圈裁剪是獨立于通過clipExtent的視窗裁剪。
projection.clipExtent(extent) // 設(shè)置投影的剪輯視窗范圍為指定的邊界(以像素為單位)。extent 范圍邊界被指定為一個數(shù)組[[x0, y0], [x1,y1]],其中x0 是視窗的左側(cè),y0 是頂部,x1 為右側(cè)和y1 是底部。如果范圍為null,則視窗裁剪不執(zhí)行。
projection.clipExtent() // 返回當前視窗裁剪的范圍,默認為null。視窗裁剪是獨立于通過clipAngle的小圈剪裁。
projection.scale(scale) // 設(shè)置投影的比例尺為特定的值,并返回投影。
projection.scale() // 返回投影的比例尺。
projection.translate(point) // 如果point 點指定了,則設(shè)置投影轉(zhuǎn)變的位移為指定的二元數(shù)組[x, y]并返回的投影。如果未指定點,則返回當前變換的位移,默認為[480, 250]。變換的位移確定投影的中心像素坐標。默認轉(zhuǎn)換位移的位置是?0°,0°?,在一個960×500區(qū)域的中心。
projection.center(location) //如果center 重心指定了,則設(shè)置投影中心為指定的位置,經(jīng)度和緯度度數(shù)的兩元數(shù)組,并返回投影。如果沒有指定中心,則返回當前的中心,默認為?0°,0°?。
projection.rotate(rotation) // 如果rotation 旋轉(zhuǎn)指定了,設(shè)置投影的三軸旋轉(zhuǎn)為指定的角度λ,φ和γ(偏航角,傾斜角和滾動角,或等效地經(jīng)度,緯度和滾動),以度并返回投影。如果rotation 未指定,返回當前缺省的轉(zhuǎn)動值[0, 0, 0]。如果rotation 指定且只有兩個值,而不是3個值,那么滾動的角度被假設(shè)為0°。
projection.precision(precision) // 如果precision 精度指定了,則設(shè)置投影自適應(yīng)重采樣的臨界值為指定的值,以像素為單位,并返回投影。此值對應(yīng)于Douglas–Peucker 距離。如果precision 精度沒有指定,則返回投影當前重采樣的精度,其精度默認為Math.SQRT(1/2)。0的精密度禁止自適應(yīng)重采樣。
projection.fitExtend(extend,object) // 設(shè)置給定范圍,對投影進行縮放和平移,以適合給定的范圍并居中。 范圍指定為數(shù)組[[x 0,y 0],[x 1,y 1]],其中x 0是邊界框的左邊,y 0是頂部,x 1是右邊,y 1是底部。 返回投影。
projection.fitSize(size,object) // fitExtend的簡單寫法,左上角為[0,0]。
antimeridian cutting:http://bl.ocks.org/mbostock/3788999
示例
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
body{ background: #21395b; }
</style>
</head>
<body>
<svg></svg>
<script src="/bower_components/d3/d3.js"></script>
<script>
var width = 1300;
var height = 1000;
var padding = 20;
var g = d3.select('svg')
.attr('width',width)
.attr('height',height)
.append('g');
var root;
var projection,path;
function color(i) { return '#0e2338'; }
d3.json('china.json',function (data) {
root = data;
//設(shè)置投影
projection = d3.geoMercator()
projection.fitExtent([[padding,padding],[width-padding*2,height-padding*2]],root);
//projection.fitSize([width,height],root);
//生成地理路徑
path = d3.geoPath(projection);
update();
});
function update() {
g.selectAll("path")
.data(root.features)
.enter()
.append("path")
.attr("stroke","#234060")
.attr("stroke-width",1)
.attr("fill", function(d,i){
return color(i);
})
.attr("d", path ) //使用地理路徑生成器
.on("mouseover",function(d,i){
d3.select(this)
.attr("fill","green");
})
.on("mouseout",function(d,i){
d3.select(this)
.attr("fill",color(i));
});
g.selectAll("text")
.data(root.features)
.enter()
.append("text")
.attr("text-anchor","middle")
.attr("dy",".3em")
.attr("fill", "#eee")
.style("font-size", "10px")
.text(function (d) {
return d.properties.name;
})
.attr("transform", function (d) {
return "translate("+projection(d.properties.cp).join(',')+")";
});
}
</script>
</body>
</html>