Javascript 使用D3.js创建人口金字塔
我需要用D3.js制作一个经典的人口金字塔。类似于此图像的内容:Javascript 使用D3.js创建人口金字塔,javascript,d3.js,population,census,Javascript,D3.js,Population,Census,我需要用D3.js制作一个经典的人口金字塔。类似于此图像的内容: 我发现了一些看起来非常好的例子,但它们比我要寻找的要复杂。有谁知道一个好的简单的例子,我可以看看吗?有什么建议吗?我是否应该制作两个相邻的条形图,每个性别组一个?制作这样的可视化效果的关键是在开始绘制任何东西之前,先花大量时间设置布局 当你需要为你的星图制作刻度和坐标时,有一些关键的测量方法可以让你的生活变得更加轻松。然后,您可以使用带有翻译的元素,以便在图表的每个“部分”中,您可以使用本地坐标 目标是创建两个镜像区域,如下所示
我发现了一些看起来非常好的例子,但它们比我要寻找的要复杂。有谁知道一个好的简单的例子,我可以看看吗?有什么建议吗?我是否应该制作两个相邻的条形图,每个性别组一个?制作这样的可视化效果的关键是在开始绘制任何东西之前,先花大量时间设置布局 当你需要为你的星图制作刻度和坐标时,有一些关键的测量方法可以让你的生活变得更加轻松。然后,您可以使用带有翻译的
元素,以便在图表的每个“部分”中,您可以使用本地坐标
目标是创建两个镜像区域,如下所示:
var width = 400,
height = 300;
var margin = {
top: 20,
right: 10
bottom: 40,
left: 10
};
var svg = d3.select('body').append('svg')
.attr('width', margin.left + width + margin.right)
.attr('height', margin.top + height + margin.bottom)
.append('g')
.attr('class', 'inner-region')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
这将允许您在两个区域之间共享相同的x和y维度比例
要定义这些区域,您可以首先为svg内部的页边距设置一些值,然后创建一个位于这些页边距内的组。这是d3可视化中的一种常见做法,如果您还不熟悉它,那么现在是学习的好时机。它通常看起来像这样:
var width = 400,
height = 300;
var margin = {
top: 20,
right: 10
bottom: 40,
left: 10
};
var svg = d3.select('body').append('svg')
.attr('width', margin.left + width + margin.right)
.attr('height', margin.top + height + margin.bottom)
.append('g')
.attr('class', 'inner-region')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
这是一个很好的实践,因为它允许您在svg文档中为轴标记、标签和标题留出空间,而不必在定位可视化本身的部分时考虑到空间。然后,如果您发现需要更多的空间,您可以只调整代码顶部的一个值,而不是重新定位整个图表
其他重要的点是两个y轴的x坐标。换句话说,男性和女性的人口为零的点(如下红线所示)。这将是与内部区域中心线的设定距离(如下蓝色线所示):
可以将中间页边距特性添加到先前创建的页边距对象中,以引用此值:
margin.middle = 28;
您需要创建变量来存储上面两条红线的位置。现在,让我们把它们称为点A
(男性人口零线的x坐标)和点B
(女性人口的对应点)
一旦设置了这些点,事情就变得简单多了,因为您可以简单地将这些值插入到svg转换中,以将创建的对象转换到这些位置
最棘手的部分是两个中心y轴,它们共享一组标签。为此,您需要掌握如何d3.svg.axis()
创建文本标签,以及可以操作哪些属性。为此,需要了解四个重要特性:
轴。定向(方向)
指定记号从轴中出来的方向。在这种情况下,这会有点混淆,因为我们希望记号指向中心,因此左轴将具有.orient('right')
,右轴将具有.orient('left')
轴。tickSize(内部、外部)
设置从轴中引出的记号标记的长度(以svg为单位)。“外部”标记是轴端点处的标记,在这种情况下可以设置为0
,因为我们使用的是带范围带的顺序标度,因此端点不表示值。为内部刻度选择一个小值,在本例中,我将使用4
轴。滴答声填充(padding)
设置标签文本的文本定位点距滴答声标记末端的距离。我们希望将文本定位点放置在图像的中心,即两个轴之间。由于我们已经知道中间边距(从中心线到每个轴的距离)和tickSize
(记号的长度),我们可以通过取这两个值的差来将它们放在中心:.tickPadding(margin.middle-4)
轴。勾号格式(格式)
指定勾号标签的格式。可以将其设置为空字符串以从其中一个轴上删除勾号标签,这样就不会发生重叠:.tickFormat(“”)
var yAxisLeft = d3.svg.axis()
.scale(yScale)
.orient('right')
.tickSize(4,0)
.tickPadding(margin.middle - 4);
var yAxisRight = d3.svg.axis()
.scale(yScale)
.orient('left')
.tickSize(4,0)
.tickFormat('');
然后,在实际绘制左y轴时,选择其
元素,并将文本定位点设置为中间
,使其以定位点为中心:
.call(yAxisLeft)
.selectAll('text')
.style('text-anchor', 'middle');
这是一个使用一些人为数据的完整图表的简单示例。我试着尽可能多地对总体结构进行评论,以便于理解。我还制作了一个translation(x,y)
函数,使每个平移的x和y坐标比使用字符串连接时更容易识别。您可以在脚本的底部找到它的定义
我希望这能有所帮助,如果您对具体细节有任何疑问,请告诉我。听起来两个条形图并排是最简单的开始方式。哇!谢谢你的回答。如果我有问题,我会告诉你。你如何在原始图形中添加代表“圣安东尼奥”人口的线条?你可以用与彩色线条相同的方式制作清晰的线条,只需将填充设置为“透明”并进行笔划。嗨,杰森利,我发布了这个问题,这是这个人口金字塔的一个变体。你能看一下吗?@jshanley回答得很好。