仅作阅读理解API文档时的参考,如有错误麻烦指正,多谢~
Map projections are sometimes implemented as point transformations.
地图投影有时会由点转换实现。
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!
如果你的球面几何由连续的无限点集合组成,这是一个合理的数学方法。 由于计算机没有无限的内存,因此我们必须使用离散的几何图形,如多边形和折线!
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使用自适应采样(受一种流行的线简化方法而启发得到的)方法来平衡精准度和性能。
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.)
多边形和折线的投影还必须处理球体与平面之间的拓扑差异。一些投影需要穿过对向子午线切割球体,另一些投影需要将球体裁剪成一个大圆。此外,球形多边形需要一个环绕的顺序约定来决定多边形的哪边是内侧: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提供了丰富的表现力:您可以为您的数据选择正确的投影和正确的方面。D3提供多种常见和不常见的地图投影。有关更多信息,请参阅 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转换为GeoJSON,请使用ogr2ogr,它是GDAL软件包的一部分。 除了地图投影,D3包括有用的球形生成器和球面数学实用工具。
安装
<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>
地图数据
如何获取中国地图的 GeoJSON 文件呢,真的有点麻烦,可以参照: https://github.com/clemsos/d3-china-map 进行制作。
Mark
- 中国地图的 GeoJSON 文件: china.geojson
- 各县的JSON地图文件:mapdata.zip
解压缩后有两个文件夹和一个 JSON 文件:
geometryCouties:各市~县的数据
geometryProvince:各省~市的数据
china.json:中国~省的数据 - 【 地图系列 】 世界地图和主要国家的 JSON 文件:
http://www.ourd3js.com/wordpress/668/
API
Paths
地理路径生成器d3.geoPath类似于d3-shape中的形状生成器:给定GeoJSON几何结构或特征对象,它生成SVG path数据字符串或渲染到Canvas的path。 动态或交互式投影中推荐使用Canvas,以提高性能。 Path数据可以在投影或变换一起使用,也可用于将平面几何直接渲染成Canvas或SVG。
var path = d3.geoPath(projection); //创建一个新的地理路径生成器。
path(object); //返回对象的路径;
path.area(object) //计算给定要素的投影面积;
path.bounds(object) //计算给定要素的投影边界。
path.centroid(object) //计算给定要素的投影中心。
path.context(context) //设置渲染上下文,可设置canvas的context。
path.context() //取得渲染上下文。
path.pointRadius(radius) //设置点要素的半径。
path.pointRadius() //取得点要素的半径。
path.projection(projection) //设置地理投影。
path.projection() //设置地理投影。
Projections(投影)
投影将球形多边形转换为平面多边形。 D3提供了几类标准投影的实现:
var projection = d3.geoMercator();
projection(point) // 投影指定的位置,参数为经纬度[longitude,latitude],获得指定位置的坐标[x,y]。
projection.invert(point) // 为指定的位置反转投影,参数为[x,y],获得指定坐标的经纬度[longitude,latitude]。
projection.stream(stream) // 包装指定的流监听器,投影输入的几何图形。
projection.clipAngle(angle) //设置投影的裁剪圆半径,指定角度并返回投影。如果角度为null,切换到子午线切割,而不是小圈的裁剪。
projection.clipAngle() //返回当前裁剪的角度,默认为空。小圈裁剪是独立于通过clipExtent的视窗裁剪。
projection.clipExtent(extent) // 设置投影的剪辑视窗范围为指定的边界(以像素为单位)。extent 范围边界被指定为一个数组[[x0, y0], [x1,y1]],其中x0 是视窗的左侧,y0 是顶部,x1 为右侧和y1 是底部。如果范围为null,则视窗裁剪不执行。
projection.clipExtent() // 返回当前视窗裁剪的范围,默认为null。视窗裁剪是独立于通过clipAngle的小圈剪裁。
projection.scale(scale) // 设置投影的比例尺为特定的值,并返回投影。
projection.scale() // 返回投影的比例尺。
projection.translate(point) // 如果point 点指定了,则设置投影转变的位移为指定的二元数组[x, y]并返回的投影。如果未指定点,则返回当前变换的位移,默认为[480, 250]。变换的位移确定投影的中心像素坐标。默认转换位移的位置是⟨0°,0°⟩,在一个960×500区域的中心。
projection.center(location) //如果center 重心指定了,则设置投影中心为指定的位置,经度和纬度度数的两元数组,并返回投影。如果没有指定中心,则返回当前的中心,默认为⟨0°,0°⟩。
projection.rotate(rotation) // 如果rotation 旋转指定了,设置投影的三轴旋转为指定的角度λ,φ和γ(偏航角,倾斜角和滚动角,或等效地经度,纬度和滚动),以度并返回投影。如果rotation 未指定,返回当前缺省的转动值[0, 0, 0]。如果rotation 指定且只有两个值,而不是3个值,那么滚动的角度被假设为0°。
projection.precision(precision) // 如果precision 精度指定了,则设置投影自适应重采样的临界值为指定的值,以像素为单位,并返回投影。此值对应于Douglas–Peucker 距离。如果precision 精度没有指定,则返回投影当前重采样的精度,其精度默认为Math.SQRT(1/2)。0的精密度禁止自适应重采样。
projection.fitExtend(extend,object) // 设置给定范围,对投影进行缩放和平移,以适合给定的范围并居中。 范围指定为数组[[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;
//设置投影
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>