d3.js地图图表绘制矩形

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了d3.js地图图表绘制矩形相关的知识,希望对你有一定的参考价值。

我正在尝试使用geojson绘制阿联酋酋长国的地图。

geojson在geojson.io上有效并验证,结果显示而不是一个矩形的地图,编写的代码在这里:

var width = 20,
height = 20;
var scal = (1 << 10) / 2 / Math.PI; 

//Define map projection 
var projection = d3.geo.mercator();
      projection
        .scale(scal)///3.5
        .translate([width/2, height/2]);

//Define path generator
var path = d3.geo.path().projection(projection);

d3.json("http://localhost/data/uae-em.json", function(error,json) {

    if(error) alert("error fetching data");
    var svg = d3.select("article")
        .append("svg")
        .attr("width",width)
        .attr("height",height);
    //draw map
    var map = svg.selectAll("path")
        .data(json.features)
        .enter()
        .append("path")
        .attr("d", path)
        .style("fill", "#3498db"); 
    });

JSON数据在这里:https://files.fm/f/ndsz3v85

以下是geojson的一个示例功能:

{"type":"Feature","id":"4","properties":{"name":"UmmAlQwain"},"geometry":{"type":"Polygon","coordinates":[[[55.2350748,25.5700834],[55.4229709,25.3989174],[55.4236655,25.3981583],[55.423986,25.3978339],[55.4254059,25.3960785],[55.4272991,25.3935724],[55.4570596,25.3762406],[55.4577152,25.375909],[55.4915399,25.3593419],[55.4926741,25.3588472],[55.4954455,25.35793],[55.5013237,25.3571279],[55.5031779,25.3570031],[55.5390972,25.3630675],[55.5909015,25.3679027],[55.5918297,25.3680754],[55.5927443,25.3683591],[55.5935906,25.3688154],[55.5943278,25.3693581],[55.5952833,25.3702339],[55.6010034,25.3768825],[55.6044809,25.3808245],[55.6295136,25.4095735],[55.630044,25.4101151],[55.6303207,25.4106671],[55.6302516,25.411542],[55.6299137,25.4123589],[55.6293946,25.413368],[55.6287288,25.4144586],[55.6280518,25.4152536],[55.6211794,25.4201663],[55.6196221,25.4209307],[55.6177489,25.4214301],[55.605742,25.4232035],[55.6024463,25.4237462],[55.5975759,25.4244245],[55.5956543,25.4249531],[55.5919637,25.4262723],[55.554199,25.4399865],[55.5518752,25.4408552],[55.5505241,25.4414505],[55.5490758,25.4421533],[55.5473004,25.4425344],[55.5456819,25.4430884],[55.5370397,25.4462406],[55.5358338,25.4466226],[55.5349558,25.4467468],[55.5337817,25.4467659],[55.523193,25.4459922],[55.5198927,25.4460304],[55.5162327,25.4457248],[55.513895,25.4454286],[55.4882538,25.4420186],[55.4870268,25.4419613],[55.4857574,25.4421332],[55.4843188,25.4426681],[55.4771469,25.4472339],[55.4709611,25.4516781],[55.324428,25.6230138],[55.3205286,25.6184125],[55.3117729,25.6106044],[55.3015804,25.5994214],[55.2892555,25.5829995],[55.2795994,25.5665793],[55.2730684,25.5680481],[55.2385191,25.570346],[55.2350748,25.5700834]]]}}
答案

这里有一些问题。

首先,你得到一个矩形的原因是因为缠绕顺序。 D3没有包含geojson规范的缠绕顺序 - 它遵循shapefile的缠绕顺序。这很奇怪,因为D3是唯一一个想到缠绕顺序在绘图方面很重要的框架,因为它使用球面几何而不是平面。在您的情况下,您正在绘制除阿联酋以外的所有内容:

enter image description here

我添加了一个笔划,我们可以看到世界的边缘(东西+/- 180度,而不是顶部,因为墨卡托在y轴上伸展到无限远,即使是圆形或截断,限制也超出了在SVG的边缘,我们还可以看到阿联酋的轮廓(或至少是它的一部分)。因此我们需要反转缠绕顺序,这意味着反转包含定义多边形中每个环的坐标的数组。

为此,我们可以使用turf.js预先准备数据,或者每次加载数据时调用它:

json.features.forEach(function(feature) {
  feature.geometry = turf.rewind(feature.geometry, {reverse:true});
})

现在我们有正确的绕组顺序数据,我们得到:

enter image description here

该功能看起来更大,因为我们可以看到所有功能,在第一张图片中,只有最后绘制的功能才真正可见:它涵盖了其余功能。

现在我们有一个不同的问题,我已经在960x500像素框架上显示了您的地图(使用您的代码(fiddle))。如果我们使用20x20帧和你的初始比例,我们什么都看不到。该地图集中在非洲海岸大西洋的[0,0]

enter image description here

广场使用您的比例和平移概述了20x20版本中显示的地图的粗糙区域,我添加了一张世界地图并将尺寸增加到200x200,以便为我们在20像素版本中看到的内容提供一些视觉背景


如果目标是展示整个世界,我们需要适当的规模。墨卡托(如果圆柱体朝北/朝南)的圆柱形投影围绕地球(沿着赤道)360度,并以地图单位将其拉伸一定距离。在d3中,比例是这个转换因子,默认假设地图上的960像素显示整个行星,地球周围是2π弧度,因此比例值为960 /2π(每2π弧度960像素)。因此,我们可以将您的比例设置为width/Math.PI/2

enter image description here

这将导致一个新问题,阿联酋大约5度跨越,世界是360度左右,这约占世界“宽度”的1%。当在20像素×20像素的SVG上显示地图时,这有点问题:UAE大约为0.2像素,这样的效果不会非常令人满意。唯一的选择是增加地图的大小,或者将地图置于阿联酋的中心位置并增加比例。

自动地图中心已被多次覆盖,我不会通过再次覆盖它来获得任何正义的先前优秀解释(我只能说v4 / 5提供了一个优秀的fitSize / fitExtent方法,但v3居中信息可以在这里找到question)。然而,为了演示,我将手动将阿联酋置于中心位置。

阿联酋的质心大约是24 N,54E(来自here)。

如果我们假设UAE比它高,并假设一个数字,例如大约5度,并且我们想要显示超过20个像素的那五度,那么我们知道世界大约是1440像素(mapWidthPixels * earthWidthDegrees / mapWidthDegrees = 20 * 360/5)。然后比例为1440/2 /π,向下舍入一点额外的余量我们得到:200。

所以使用:

var width = 20;
var height = 20;
var scale = 200;
var center = [54,24];

我们可以得到这个:

enter image description here

仍然很小,但有了上述原则,很容易扩大。

fiddle

我已经为上面的20px SVG添加了一个边框,为SVG提供了一个边界,因为它的尺寸很小,并且缺少SVG边缘的区别。

以上是关于d3.js地图图表绘制矩形的主要内容,如果未能解决你的问题,请参考以下文章

D3.js-柱形图

D3.js 基于数据的绘图

Javascript / D3.js - 绘制大型数据集 - 提高 d3.js 绘制的 svg 图表中的缩放和平移速度

使用D3.js绘制地图并打点

d3.js 图形输出成高分辨率打印质量文件?

线条未正确显示d3.js geo和google地图