dc.js 如何在行图中创建目标线
How to create target lines in a rowchart in dc.js
我正在使用行图来显示销售员按项目分类的总销售额。
已经像 google 中的许多帖子一样尝试了复合图表但未成功,但是 none 示例使用了行图。
我需要像图片一样,创建红线来代表每件商品的销售价值目标,但我不知道怎么做,你们能帮帮我吗?谢谢!
实际上这是我绘制行图的代码
spenderRowChart = dc.rowChart("#chart-row-spenders");
spenderRowChart
.width(450).height(200)
.dimension(itemDim)
.group(totalItemGroup)
.elasticX(true);
显然您需要目标数据的来源,它可以是全球地图或数据中的字段。
我创建了 an example 从全局中提取数据,但如果您的组缩减提供了一个名为 target
的字段,它也会从数据中提取数据。
然后,它向每一行添加一个新的 path
元素。方便的是,这些行已经是 SVG g
group elements,因此放入其中的任何内容都已经偏移到行 rect 的左上角。
我们唯一缺少的坐标是矩形的高度,我们可以通过从现有柱之一读取它来获得它:
var height = chart.select('g.row rect').attr('height');
然后我们 select g
并使用通用更新模式为每个 path.target
添加一个 path.target
(如果没有的话)。我们将其设置为红色,仅当我们有该行的数据时才可见,并将其从 X 0 开始,以便它从左侧开始动画,就像行矩形一样:
var target = chart.selectAll('g.row')
.selectAll('path.target').data(function(d) { return [d]; });
target = target.enter().append('path')
.attr('class', 'target')
.attr('stroke', 'red')
.attr('visibility', function(d) {
return (d.value.target !== undefined || _targets[d.key] !== undefined) ? 'visible' : 'hidden';
})
.attr('d', function(d) {
return 'M0,0 v' + height;
}).merge(target);
最后的 .merge(target)
将这个 selection 合并到主 selection 中。
现在我们可以将所有目标线设置为动画:
target.transition().duration(chart.transitionDuration())
.attr('visibility', function(d) {
return (d.value.target !== undefined || _targets[d.key] !== undefined) ? 'visible' : 'hidden';
})
.attr('d', function(d) {
return 'M' + (chart.x()(d.value.target || _targets[d.key] || 0)+0.5) + ',0 v' + height;
});
该示例未显示,但这也将允许目标在目标发生变化或比例发生变化时动态移动。同样,如果数据为 added/removed.
,目标也可能变得可见或不可见
谢谢,由于很长时间才得到答案,我已经开发了一个解决方案,但是,真的谢谢你,它非常好,因为它的想法几乎相同,所以我认为很高兴分享代码这里也是
不同之处在于我的代码我使用其他逻辑来清除笔划并使用其他图表的过滤器值使其动态化。
.renderlet(function(chart) {
dc.events.trigger(function() {
filter1 = yearRingChart.filters();
filter2 = spenderRowChart.filters();
});
})
.on('pretransition', function(chart) {
if (aux_path.length > 0){
for (i = 0; i < aux_path.length; i++){
aux_path[i].remove();
}
};
aux_data = JSON.parse(JSON.stringify(data2));
aux_data = aux_data.filter(venda => filter1.indexOf(venda.Nome) > -1);
meta_subgrupo = [];
aux_data.forEach(function(o) {
var existing = meta_subgrupo.filter(function(i) { return i.SubGrupo === o.SubGrupo })[0];
if (!existing)
meta_subgrupo.push(o);
else
existing.Meta += o.Meta;
});
if (filter1.length > 0) {
for (i = 0; (i < Object.keys(subGrupos).length); i++){
var x_vert = meta_subgrupo[i].Meta;
var extra_data = [
{x: chart.x()(x_vert), y: 0},
{x: chart.x()(x_vert), y: chart.effectiveHeight()}
];
var line = d3.line()
.x(function(d) { return d.x; })
.y(function(d) { return d.y; })
.curve(d3.curveLinear);
var chartBody = chart.select('g');
var path = chartBody.selectAll('path.extra').data([extra_data]);
path = path.enter()
.append('path')
.attr('class', 'oeExtra')
.attr('stroke', subGruposColors[i].Color)
.attr('id', 'ids')
.attr("stroke-width", 2)
.style("stroke-dasharray", ("10,3"))
.merge(path)
path.attr('d', line);
aux_path.push(path);
}
}
})
这就是它的样子
我正在使用行图来显示销售员按项目分类的总销售额。
已经像 google 中的许多帖子一样尝试了复合图表但未成功,但是 none 示例使用了行图。
我需要像图片一样,创建红线来代表每件商品的销售价值目标,但我不知道怎么做,你们能帮帮我吗?谢谢!
实际上这是我绘制行图的代码
spenderRowChart = dc.rowChart("#chart-row-spenders");
spenderRowChart
.width(450).height(200)
.dimension(itemDim)
.group(totalItemGroup)
.elasticX(true);
显然您需要目标数据的来源,它可以是全球地图或数据中的字段。
我创建了 an example 从全局中提取数据,但如果您的组缩减提供了一个名为 target
的字段,它也会从数据中提取数据。
然后,它向每一行添加一个新的 path
元素。方便的是,这些行已经是 SVG g
group elements,因此放入其中的任何内容都已经偏移到行 rect 的左上角。
我们唯一缺少的坐标是矩形的高度,我们可以通过从现有柱之一读取它来获得它:
var height = chart.select('g.row rect').attr('height');
然后我们 select g
并使用通用更新模式为每个 path.target
添加一个 path.target
(如果没有的话)。我们将其设置为红色,仅当我们有该行的数据时才可见,并将其从 X 0 开始,以便它从左侧开始动画,就像行矩形一样:
var target = chart.selectAll('g.row')
.selectAll('path.target').data(function(d) { return [d]; });
target = target.enter().append('path')
.attr('class', 'target')
.attr('stroke', 'red')
.attr('visibility', function(d) {
return (d.value.target !== undefined || _targets[d.key] !== undefined) ? 'visible' : 'hidden';
})
.attr('d', function(d) {
return 'M0,0 v' + height;
}).merge(target);
最后的 .merge(target)
将这个 selection 合并到主 selection 中。
现在我们可以将所有目标线设置为动画:
target.transition().duration(chart.transitionDuration())
.attr('visibility', function(d) {
return (d.value.target !== undefined || _targets[d.key] !== undefined) ? 'visible' : 'hidden';
})
.attr('d', function(d) {
return 'M' + (chart.x()(d.value.target || _targets[d.key] || 0)+0.5) + ',0 v' + height;
});
该示例未显示,但这也将允许目标在目标发生变化或比例发生变化时动态移动。同样,如果数据为 added/removed.
,目标也可能变得可见或不可见谢谢,由于很长时间才得到答案,我已经开发了一个解决方案,但是,真的谢谢你,它非常好,因为它的想法几乎相同,所以我认为很高兴分享代码这里也是
不同之处在于我的代码我使用其他逻辑来清除笔划并使用其他图表的过滤器值使其动态化。
.renderlet(function(chart) {
dc.events.trigger(function() {
filter1 = yearRingChart.filters();
filter2 = spenderRowChart.filters();
});
})
.on('pretransition', function(chart) {
if (aux_path.length > 0){
for (i = 0; i < aux_path.length; i++){
aux_path[i].remove();
}
};
aux_data = JSON.parse(JSON.stringify(data2));
aux_data = aux_data.filter(venda => filter1.indexOf(venda.Nome) > -1);
meta_subgrupo = [];
aux_data.forEach(function(o) {
var existing = meta_subgrupo.filter(function(i) { return i.SubGrupo === o.SubGrupo })[0];
if (!existing)
meta_subgrupo.push(o);
else
existing.Meta += o.Meta;
});
if (filter1.length > 0) {
for (i = 0; (i < Object.keys(subGrupos).length); i++){
var x_vert = meta_subgrupo[i].Meta;
var extra_data = [
{x: chart.x()(x_vert), y: 0},
{x: chart.x()(x_vert), y: chart.effectiveHeight()}
];
var line = d3.line()
.x(function(d) { return d.x; })
.y(function(d) { return d.y; })
.curve(d3.curveLinear);
var chartBody = chart.select('g');
var path = chartBody.selectAll('path.extra').data([extra_data]);
path = path.enter()
.append('path')
.attr('class', 'oeExtra')
.attr('stroke', subGruposColors[i].Color)
.attr('id', 'ids')
.attr("stroke-width", 2)
.style("stroke-dasharray", ("10,3"))
.merge(path)
path.attr('d', line);
aux_path.push(path);
}
}
})
这就是它的样子