在上一篇文章中 ,我们学习了如何使用D3.js (用于创建数据驱动的文档的JavaScript库)来实现气泡图。 D3.js可帮助使用HTML,SVG和CSS可视化数据。 在本文中,我们将看到如何使用D3.js来实现折线图和条形图。 在继续之前,您应该下载D3.js并熟悉我之前的文章中的内容 。
创建折线图
首先,我们需要一些数据进行绘制。 我们将使用以下数据。
var lineData = [{
x: 1,
y: 5
}, {
x: 20,
y: 20
}, {
x: 40,
y: 10
}, {
x: 60,
y: 40
}, {
x: 80,
y: 5
}, {
x: 100,
y: 60
}];
我们还需要一个<svg>
元素来绘制图形。
<svg id="visualisation" width="1000" height="500"></svg>
接下来,我们需要创建x和y轴,为此,我们需要声明一个域和范围。 域定义了图表上显示的最小值和最大值,而范围是我们将覆盖的SVG的数量。 两个轴都需要根据lineData
的数据进行lineData
,这意味着我们必须相应地设置域和范围。 绘制轴的代码如下所示。
var vis = d3.select('#visualisation'),
WIDTH = 1000,
HEIGHT = 500,
MARGINS = {
top: 20,
right: 20,
bottom: 20,
left: 50
},
xRange = d3.scale.linear().range([MARGINS.left, WIDTH - MARGINS.right]).domain([d3.min(lineData, function(d) {
return d.x;
}), d3.max(lineData, function(d) {
return d.x;
})]),
yRange = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([d3.min(lineData, function(d) {
return d.y;
}), d3.max(lineData, function(d) {
return d.y;
})]),
xAxis = d3.svg.axis()
.scale(xRange)
.tickSize(5)
.tickSubdivide(true),
yAxis = d3.svg.axis()
.scale(yRange)
.tickSize(5)
.orient('left')
.tickSubdivide(true);
vis.append('svg:g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + (HEIGHT - MARGINS.bottom) + ')')
.call(xAxis);
vis.append('svg:g')
.attr('class', 'y axis')
.attr('transform', 'translate(' + (MARGINS.left) + ',0)')
.call(yAxis);
在此代码中,我们为图形定义了WIDTH
, HEIGHT
和MARGINS
。 xRange
和yRange
变量代表相应轴的域。 我们根据左右边界设置轴的范围。
接下来,由于域是我们将在图形上显示的数据,因此我们需要从lineData
获得最小值和最大值。 这是使用d3.max()
和d3.min()
方法完成的。
接下来,我们根据xRange
和yRange
变量创建了轴。 对于两个轴,我们分别将X和Y轴的比例尺定义为xRange
和yRange
。 然后,我们仅将两个轴都附加到SVG并应用了变换。 现在,如果我们看一下Y轴,则需要将其向左定向。 因此,我们向yAxis
施加了左方向。 我们对两个轴都进行了变换,同时保留了定义的边距,以使轴不接触SVG边距。
这是上述代码的演示 ,显示了两个轴。
接下来,我们需要将xRange
和yRange
应用于坐标,以将它们转换为绘图空间并在绘图空间上绘制一条线。 我们将使用d3.svg.line()
绘制折线图。 为此,我们需要创建一个线生成器函数,该函数从数据中返回x和y坐标以绘制线。 这就是我们定义行生成器函数的方式:
var lineFunc = d3.svg.line()
.x(function(d) {
return xRange(d.x);
})
.y(function(d) {
return yRange(d.y);
})
.interpolate('linear');
interpolate('linear')
调用告诉D3绘制直线。
接下来,我们需要将SVG路径的d
属性设置为从line函数返回的坐标。 使用以下代码可完成此操作。
vis.append('svg:path')
.attr('d', lineFunc(lineData))
.attr('stroke', 'blue')
.attr('stroke-width', 2)
.attr('fill', 'none');
我们使用stroke
设置了线条颜色。 线条的宽度是使用stroke-width
定义的。 我们已将fill
设置为none
,以免不填充图形边界。 这是使用linear
插值的折线图演示 ,这是使用basis
插值的线图演示 。
创建条形图
接下来,我们将看看创建条形图。 由于我们已经创建了轴,因此不需要重新发明轮子。 但是,我们将稍微修改现有代码。 首先,示例数据和用于创建图表坐标轴的代码:
function InitChart() {
var barData = [{
'x': 1,
'y': 5
}, {
'x': 20,
'y': 20
}, {
'x': 40,
'y': 10
}, {
'x': 60,
'y': 40
}, {
'x': 80,
'y': 5
}, {
'x': 100,
'y': 60
}];
var vis = d3.select('#visualisation'),
WIDTH = 1000,
HEIGHT = 500,
MARGINS = {
top: 20,
right: 20,
bottom: 20,
left: 50
},
xRange = d3.scale.linear().range([MARGINS.left, WIDTH - MARGINS.right]).domain([d3.min(barData, function(d) {
return d.x;
}),
d3.max(barData, function (d) {
return d.x;
})
]),
yRange = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([d3.min(barData, function(d) {
return d.y;
}),
d3.max(barData, function (d) {
return d.y;
})
]),
xAxis = d3.svg.axis()
.scale(xRange)
.tickSize(5)
.tickSubdivide(true),
yAxis = d3.svg.axis()
.scale(yRange)
.tickSize(5)
.orient("left")
.tickSubdivide(true);
vis.append('svg:g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + (HEIGHT - MARGINS.bottom) + ')')
.call(xAxis);
vis.append('svg:g')
.attr('class', 'y axis')
.attr('transform', 'translate(' + (MARGINS.left) + ',0)')
.call(yAxis);
}
InitChart();
这是先前代码的演示 。 如果您查看Y轴,则比例从5开始。 这个最小值来自我们的样本数据,其中5是最小Y值。 因此,我们需要将Y轴从0缩放。为此,我们需要在InitChart()
函数中修改yRange
的域,如下所示:
yRange = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([0,
d3.max(barData, function(d) {
return d.y;
})]);
对于条形图,我们将使用ordinal
比例尺而不是linear
比例尺。 序数标度有助于维护离散域。 有关更详细的信息,请参阅序数表上的官方文档 。
我们还将使用rangeRoundBands
在图表条上划分宽度。 我们会在修改xRange
使用ordinal
规模和rangeRoundBands
,如下图所示。 请注意,我们还将条形图之间的间距设置为0.1。
xRange = d3.scale.ordinal().rangeRoundBands([MARGINS.left, WIDTH - MARGINS.right], 0.1).domain(barData.map(function(d) {
return d.x;
}));
接下来,我们需要为图表数据创建矩形条。 我们将使用x和y坐标设置矩形条的height
和width
,将示例数据绑定到矩形。 代码如下:
vis.selectAll('rect')
.data(barData)
.enter()
.append('rect')
.attr('x', function(d) { // sets the x position of the bar
return xRange(d.x);
})
.attr('y', function(d) { // sets the y position of the bar
return yRange(d.y);
})
.attr('width', xRange.rangeBand()) // sets the width of bar
.attr('height', function(d) { // sets the height of bar
return ((HEIGHT - MARGINS.bottom) - yRange(d.y));
})
.attr('fill', 'grey'); // fills the bar with grey color
这是运行中的条形图的演示 。
添加活动
为了提高交互性,我们还可以将事件附加到栏上。 我们可以附加一个事件来突出显示mouseover
的栏。 这是可以实现的方法:
vis.selectAll('rect')
.data(barData)
.enter()
.append('rect')
.attr('x', function(d) {
return xRange(d.x);
})
.attr('y', function(d) {
return yRange(d.y);
})
.attr('width', xRange.rangeBand())
.attr('height', function(d) {
return ((HEIGHT - MARGINS.bottom) - yRange(d.y));
})
.attr('fill', 'grey')
.on('mouseover', function(d) {
d3.select(this)
.attr('fill', 'blue');
});
在此代码中, on('mouseover')
添加了一个事件处理程序,该事件处理程序在鼠标悬停时调用,这使悬停的条变为蓝色。 这是演示此效果的演示 。
您可能会注意到, mouseout
,这些条不会再次变为灰色。 让我们附加另一个事件,以在鼠标移出时将其恢复为先前的颜色。 更新后的代码如下所示:
vis.selectAll('rect')
.data(barData)
.enter()
.append('rect')
.attr('x', function(d) {
return xRange(d.x);
})
.attr('y', function(d) {
return yRange(d.y);
})
.attr('width', xRange.rangeBand())
.attr('height', function(d) {
return ((HEIGHT - MARGINS.bottom) - yRange(d.y));
})
.attr('fill', 'grey')
.on('mouseover', function(d) {
d3.select(this)
.attr('fill', 'blue');
})
.on('mouseout', function(d) {
d3.select(this)
.attr('fill', 'grey');
});
并且,这里是上述代码的演示示例 。
结论
D3.js是一个很棒的JavaScript库,用于数据可视化。 在本教程中,我们着重于创建相当简单的条形图和折线图。 如果您有兴趣进行更多实验,请尝试从D3库向本文的图表中添加其他可视化技术。
From: https://www.sitepoint.com/creating-simple-line-bar-charts-using-d3-js/