如何突出显示折线图上的最大点和最小点
how to highlight max and min points on lineChart
我使用 dc.js 折线图和条形图。现在我需要用 'renderArea(true)'.
在折线图上标记最大值和最小值
我想要下图这样的东西或者其他东西,但我不知道如何添加这个功能。
更新:
戈登的回答很完美。不幸的是,我的图表没有在标记点
上显示带有 'mouseover' 的提示
再更新一次:
缩放后如何重新绘制这些点?
dc.js 不直接支持此功能,但您可以使用 renderlet 对图表进行注释。很高兴,dc.js 当您需要像这样的自定义注释时,可以轻松地转义到 d3。
我们将使用这样一个事实,即默认情况下折线图在每个数据点处绘制不可见的点(只有将鼠标悬停在上面时才会出现)。我们将从中获取坐标并使用它们在另一层中绘制或更新我们自己的点。
通常我们希望使用过渡前事件处理程序,但这些点似乎在过渡之后才具有位置,因此我们必须改为处理 renderlet 事件:
chart.on('renderlet', function(chart) { // 1
// create a layer for the highlights, only once
// insert it after the tooltip/dots layer
var highlightLayer = chart.select('g.chart-body') // 2
.selectAll('g.highlight-dots').data([0]);
highlightLayer
.enter().insert('g', 'g.dc-tooltip-list').attr('class', 'highlight-dots');
chart.selectAll('g.dc-tooltip').each(function(_, stacki) { // 3
var dots = d3.select(this).selectAll('circle.dot'); // 4
var data = dots.data();
var mini = 0, maxi = 0;
data.forEach(function(d, i) { // 5
if(i===0) return;
if(d.y < data[mini].y)
mini = i;
if(d.y > data[maxi].y)
maxi = i;
});
var highlightData = [mini, maxi].map(function(i) { // 6
var dot = dots.filter(function(_, j) { return j === i; });
return {
x: dot.attr('cx'),
y: dot.attr('cy'),
color: dot.attr('fill')
}
});
var highlights = highlightLayer.selectAll('circle.minmax-highlight._' + stacki).data(highlightData);
highlights
.enter().append('circle') // 7
.attr({
class: 'minmax-highlight _' + stacki,
r: 10,
'fill-opacity': 0.2,
'stroke-opacity': 0.8
});
highlights.attr({ // 8
cx: function(d) { return d.x; },
cy: function(d) { return d.y; },
stroke: function(d) { return d.color; },
fill: function(d) { return d.color; }
});
});
});
这个比较复杂,让我们一步步来看:
- 我们正在侦听 renderlet 事件,该事件会在一切都已转换后触发
- 我们将创建另一个图层。
.data([0]).enter().insert(stuff)
技巧是 d3 general update pattern that just makes sure an item is added exactly once. We specify the selector for the existing tooltip/dots layer as the second parameter to .insert()
, in order to put this layer before in DOM order, which means behind. Also, we'll hold onto the update selection 的退化情况,因为它要么是插入的节点,要么是现有的节点。
- 我们遍历每个工具提示点堆栈
- 在每个堆栈中,我们将 select 所有现有的点,
- 并遍历所有数据,找到最小和最大索引
mini
和 maxi
.
- 现在我们将创建一个双元素数据数组来绑定到 min/max 高亮点,从现有点中提取数据
- 现在我们终于可以开始画东西了。我们将使用相同的退化更新模式来绘制两个点 class
minmax-highlight _1
、_2
等
- 并使用我们在第 6 步中记住的颜色和位置
请注意,每个堆栈的最小值和最大值不一定与总最小值和最大值相同,因此较高堆栈的突出显示点可能不是最高点或最低点。
没那么简单,但如果您愿意进行一些 d3 黑客攻击,也不会难。
示例 fiddle:http://jsfiddle.net/gordonwoodhull/7vptdou5/31/
我使用 dc.js 折线图和条形图。现在我需要用 'renderArea(true)'.
在折线图上标记最大值和最小值我想要下图这样的东西或者其他东西,但我不知道如何添加这个功能。
更新:
戈登的回答很完美。不幸的是,我的图表没有在标记点
上显示带有 'mouseover' 的提示再更新一次:
缩放后如何重新绘制这些点?
dc.js 不直接支持此功能,但您可以使用 renderlet 对图表进行注释。很高兴,dc.js 当您需要像这样的自定义注释时,可以轻松地转义到 d3。
我们将使用这样一个事实,即默认情况下折线图在每个数据点处绘制不可见的点(只有将鼠标悬停在上面时才会出现)。我们将从中获取坐标并使用它们在另一层中绘制或更新我们自己的点。
通常我们希望使用过渡前事件处理程序,但这些点似乎在过渡之后才具有位置,因此我们必须改为处理 renderlet 事件:
chart.on('renderlet', function(chart) { // 1
// create a layer for the highlights, only once
// insert it after the tooltip/dots layer
var highlightLayer = chart.select('g.chart-body') // 2
.selectAll('g.highlight-dots').data([0]);
highlightLayer
.enter().insert('g', 'g.dc-tooltip-list').attr('class', 'highlight-dots');
chart.selectAll('g.dc-tooltip').each(function(_, stacki) { // 3
var dots = d3.select(this).selectAll('circle.dot'); // 4
var data = dots.data();
var mini = 0, maxi = 0;
data.forEach(function(d, i) { // 5
if(i===0) return;
if(d.y < data[mini].y)
mini = i;
if(d.y > data[maxi].y)
maxi = i;
});
var highlightData = [mini, maxi].map(function(i) { // 6
var dot = dots.filter(function(_, j) { return j === i; });
return {
x: dot.attr('cx'),
y: dot.attr('cy'),
color: dot.attr('fill')
}
});
var highlights = highlightLayer.selectAll('circle.minmax-highlight._' + stacki).data(highlightData);
highlights
.enter().append('circle') // 7
.attr({
class: 'minmax-highlight _' + stacki,
r: 10,
'fill-opacity': 0.2,
'stroke-opacity': 0.8
});
highlights.attr({ // 8
cx: function(d) { return d.x; },
cy: function(d) { return d.y; },
stroke: function(d) { return d.color; },
fill: function(d) { return d.color; }
});
});
});
这个比较复杂,让我们一步步来看:
- 我们正在侦听 renderlet 事件,该事件会在一切都已转换后触发
- 我们将创建另一个图层。
.data([0]).enter().insert(stuff)
技巧是 d3 general update pattern that just makes sure an item is added exactly once. We specify the selector for the existing tooltip/dots layer as the second parameter to.insert()
, in order to put this layer before in DOM order, which means behind. Also, we'll hold onto the update selection 的退化情况,因为它要么是插入的节点,要么是现有的节点。 - 我们遍历每个工具提示点堆栈
- 在每个堆栈中,我们将 select 所有现有的点,
- 并遍历所有数据,找到最小和最大索引
mini
和maxi
. - 现在我们将创建一个双元素数据数组来绑定到 min/max 高亮点,从现有点中提取数据
- 现在我们终于可以开始画东西了。我们将使用相同的退化更新模式来绘制两个点 class
minmax-highlight _1
、_2
等 - 并使用我们在第 6 步中记住的颜色和位置
请注意,每个堆栈的最小值和最大值不一定与总最小值和最大值相同,因此较高堆栈的突出显示点可能不是最高点或最低点。
没那么简单,但如果您愿意进行一些 d3 黑客攻击,也不会难。
示例 fiddle:http://jsfiddle.net/gordonwoodhull/7vptdou5/31/