我正在尝试使用类似于example的d3js和nvd3.js实现“堆积面积图”。此外,我想使用this one这样的上下文画笔来选择日期范围,这会影响堆积面积图。实际上,这已经在起作用,但是一旦选定的日期范围不包含第一个日期,它就会以某种方式在Y轴上方绘制一些线。请看下面的图片:
这是我的代码:
堆积面积图
var margin = {
top : 10,
right : 20,
bottom : 100,
left : 20
}, width = 960, height = 300;
var svg_stack = d3.select("#stack").append("svg").attr("width", width + margin.left + margin.right).attr("height", (height + margin.top + margin.bottom));
function initStackChart() {
nv.addGraph(function() {
var chart = nv.models.stackedAreaChart().x(function(d) {
return Date.parse(new Date(d[0]))
}).y(function(d) {
return d[1]
}).clipEdge(false);
chart.xAxis.tickFormat(function(d) {
return d3.time.format('%x')(new Date(d))
});
chart.yAxis.tickFormat(d3.format(',.2f'));
if (!!time_range) {
chart.xDomain([time_range[0], time_range[1]]);
}
d3.select('#stack svg').datum(temp_data).transition().duration(100).call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
}
画笔
var margin = {top: 10, right: 20, bottom: 0, left: 20},
width = 960,
height = 50;
var contextHeight = 50;
contextWidth = width;
var parseDate = d3.time.format("%Y-%m-%d").parse;
var x = d3.time.scale().range([0, width]),
y = d3.scale.linear().range([contextHeight, 0]);
var xAxis = d3.svg.axis().scale(x).tickSize(contextHeight).tickPadding(-10).orient("bottom");
var brush = d3.svg.brush()
.x(x)
.on("brush", brushed);
var area2 = d3.svg.area()
.interpolate("monotone")
.x(function(d) { return x(d.time); })
.y0(contextHeight)
.y1(0);
var svg_brush = d3.select("#brush").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
svg_brush.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
var context = svg_brush.append("g").attr("class","context")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
function initBrush(data)
{
x.domain(d3.extent(data.map(function(d) { return d.time; })));
context.append("g")
.attr("class", "x axis top")
.attr("transform", "translate(0,0)")
.call(xAxis);
context.append("g")
.attr("class", "x brush")
.call(brush)
.selectAll("rect")
.attr("y", 0)
.attr("height", contextHeight);
};
function brushed() {
var b = brush.empty() ? x.domain() : brush.extent();
console.log(b);
time_range=b;
initStackChart();
}
数据
var temp_data = [
{
key: "Node0",
values:
[
[ 1364795940000, 10 ],
[ 1365020480000, 30 ],
[ 1365630480000, 30 ],
[ 1366000480012, 30 ],
[ 1366012740000, 0 ]
]
},
{
key: "Node1",
values:
[
[ 1364795940000, 10 ],
[ 1365020480000, 20 ],
[ 1365630480000, 34 ],
[ 1366000480012, 82 ],
[ 1366012740000, 0 ]
]
},
{
key: "Node2",
values:
[
[ 1364795940000, 20 ],
[ 1365020480000, 10 ],
[ 1365630480000, 0 ],
[ 1366000480012, 100 ],
[ 1366012740000, 80 ]
]
},
{
key: "Node3",
values:
[
[ 1364795940000, 10 ],
[ 1365020480000, 60 ],
[ 1365630480000, 10 ],
[ 1366000480012, 10 ],
[ 1366012740000, 10 ]
]
},
{
key: "Node4",
values:
[
[ 1364795940000, 16 ],
[ 1365020480000, 32 ],
[ 1365630480000, 10 ],
[ 1366000480012, 90 ],
[ 1366012740000, 10 ]
]
},
{
key: "Node5",
values:
[
[ 1364795940000, 10 ],
[ 1365020480000, 50 ],
[ 1365630480000, 10 ],
[ 1366000480012, 20 ],
[ 1366012740000, 110 ]
]
},
{
key: "Node6",
values:
[
[ 1364795940000, 19 ],
[ 1365020480000, 55 ],
[ 1365630480000, 32 ],
[ 1366000480012, 12 ],
[ 1366012740000, 12 ]
]
},
{
key: "Node7",
values:
[
[ 1364795940000, 0 ],
[ 1365020480000, 20 ],
[ 1365630480000, 40 ],
[ 1366000480012, 30 ],
[ 1366012740000, 20 ]
]
},
{
key: "Node8",
values:
[
[ 1364795940000, 12 ],
[ 1365020480000, 31 ],
[ 1365630480000, 40 ],
[ 1366000480012, 20 ],
[ 1366012740000, 15 ]
]
},
{
key: "Node9",
values:
[
[ 1364795940000, 10 ],
[ 1365020480000, 35 ],
[ 1365630480000, 50 ],
[ 1366000480012, 30 ],
[ 1366012740000, 90 ]
]
}
]
谢谢你。
最佳答案
在图表设置中将.clipEdge(false);
更改为.clipEdge(true);
。
编辑
好的,我设法使用以下代码在NVD3 live code site上重新创建了您的问题(数据和标记与它们的堆积图示例相同):
nv.addGraph(function() {
var chart = nv.models.stackedAreaChart()
.x(function(d) { return d[0] })
.y(function(d) { return d[1] })
.clipEdge(true);
var chart2 = nv.models.stackedAreaChart()
.x(function(d) { return d[0] })
.y(function(d) { return d[1] })
.xDomain([1096516800000, 1270008000000])
.clipEdge(true);
chart.xAxis
.showMaxMin(false)
.tickFormat(function(d) { return d3.time.format('%x')(new Date(d)) });
chart.yAxis
.tickFormat(d3.format(',.2f'));
chart2.xAxis
.showMaxMin(false)
.tickFormat(function(d) { return d3.time.format('%x')(new Date(d)) });
chart2.yAxis
.tickFormat(d3.format(',.2f'));
d3.select('#chart svg')
.datum(data)
.transition().duration(500).call(chart)
.transition().delay(3000).duration(500)
.call(chart2);
nv.utils.windowResize(chart.update);
return chart2;
});
基本上,这就是您要做的-创建一个全新的图表函数,并在同一容器上调用它。图表功能主要选择所有相同的对象,并更改其属性-从而实现平滑过渡。但是,它提供给
<clipPath>
元素的随机ID代码(以确保每个元素具有唯一的ID)不再与其用作“剪切路径”属性的ID代码匹配。您可以在NVD3代码中将其称为错误,但这也部分是因为您以意外的方式使用了该函数。相反,如果我使用以下代码:
nv.addGraph(function() {
var chart = nv.models.stackedAreaChart()
.x(function(d) { return d[0] })
.y(function(d) { return d[1] })
.clipEdge(true);
chart.xAxis
.showMaxMin(false)
.tickFormat(function(d) { return d3.time.format('%x')(new Date(d)) });
chart.yAxis
.tickFormat(d3.format(',.2f'));
var svg = d3.select('#chart svg')
.datum(data)
.transition().duration(500).call(chart);
nv.utils.windowResize(chart.update);
var change = window.setTimeout(function(){
chart.xDomain([1096516800000, 1270008000000]);
chart.update();
}, 3000);
return chart;
});
剪切路径仍然可以正常工作。注意区别吗?我没有创建和调用整个新的图表函数,而是使用新的域更新了图表函数,并调用了该函数的
update()
方法。尝试重新安排您的涂刷功能以这种方式进行更新,不仅应该修复剪切路径问题,而且代码也应该更快。编辑2
那么如何用您的原始代码来实现呢?
首先,您需要将在
nv.addGraph()
中创建的图表函数对象保存到一个可由brushed()
函数访问的变量中。然后,在
brushed()
函数中,修改保存的图表函数以应用新的x域,然后调用函数对象的update方法。var margin = {
top : 10,
right : 20,
bottom : 100,
left : 20
}, width = 960, height = 300;
var chart; // NEW! declare a variable that can be accessed by both
// initialization and update functions
var svg_stack = d3.select("#stack")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", (height + margin.top + margin.bottom));
function initStackChart() {
nv.addGraph(function() {
chart = nv.models.stackedAreaChart()
// NEW! no "var" statement!
// this gets assigned to the chart variable declared above
/* rest of chart initialization code, the same as before */
});
}
/* All the initialization code for the timeline brushing goes here, until: */
function brushed() {
var b = brush.empty() ? x.domain() : brush.extent();
console.log(b);
time_range=b;
chart.xDomain(b); //modify the saved chart object
chart.update(); //update the chart using the saved function
}
关于javascript - nvd3js中的堆积面积图-X轴溢出,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21190421/