我使用d3js作为交互式图表,您可以在其中输入数据,图表值将会更新。该图表是具有{date,value}对的基本二维折线图。这是我每次有新数据更新时使用的代码,用于刷新图表:
function fetchLatest()
{
// get data from server
$.getJSON('/dataset',
function(data)
{
var data_etl = [];
data_etl = data.map(function(d){
return { x: parseDate(d.date), y: d.value };
});
var xScale = d3.scale.ordinal().rangeRoundPoints([0, options.width - 97]);
var yScale = d3.scale.linear();
chart
.width($('.livechart').width())
.height(300)
.x(xScale.domain(data_etl.map(function(d){ return d.x; })));
.y(yScale.domain([0, d3.max(data_etl, function(d) { return d.y;} )+1])); // PROBLEM LINE
chart.replaceSeries(data_etl);
chart.render();
});
}
问题在于,虽然图表在第一次加载时看起来很完美,但在重新加载(新数据更新)时,y比例完全被压扁(因此线条变为平坦的水平线)。我做了一些调试,并将问题精确定位到这一行:
.y(yScale.domain([0, d3.max(data_etl, function(d) { return d.y;} )+1]));
如果在更新,我不会调用此行,那么图表会更新。但是,如果我将其调用,则会导致上述问题。有谁知道为什么会这样?
修改来自meetamit的每条记事,没有足够的信息。我也添加了图表对象代码:
function lineChart(insertionPoint) {
var _chart = {};
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d) {
var tip_date = "<span style='color:#f78b20'>" + formatDate(d.x) + ": </span>";
var tip_activity = d.y;
return tip_date + tip_activity;
});
var _width = 600, _height = 300,
_margins = {top: 40, left: 40, right: 40, bottom: 40},
_x, _y,
_data = [],
_colors = d3.scale.ordinal().range([
'#33ccff', '#f78b20', '#99dc2a', '#57d4d3'
]),
_svg,
_bodyG,
_line;
_chart.render = function () {
if (!_svg) {
_svg = d3.select(insertionPoint).append("svg") // <-2B
.attr("height", _height)
.attr("width", _width);
renderAxes(_svg);
defineBodyClip(_svg);
}
renderBody(_svg);
_svg.call(tip);
};
function renderAxes(svg) {
var axesG = svg.append("g")
.attr("class", "axes");
renderXAxis(axesG);
renderYAxis(axesG);
}
function renderXAxis(axesG){
// xAxis
var xAxis = d3.svg.axis()
//.scale(_x.range([0, quadrantWidth()]))
.scale(_x)
.orient("bottom")
.tickFormat(d3.time.format("%m-%d"));
axesG.append("g")
.attr("class", "x axis")
.attr("transform", function () {
return "translate(" + xStart() + "," + yStart() + ")";
})
.call(xAxis);
}
function renderYAxis(axesG){
//yAxis
var yAxis = d3.svg.axis()
.scale(_y.range([quadrantHeight(), 0]))
.orient("left");
axesG.append("g")
.attr("class", "y axis")
.attr("transform", function () {
return "translate(" + xStart() + "," + yEnd() + ")";
})
.call(yAxis);
}
function defineBodyClip(svg) {
var padding = 5;
svg.append("defs")
.append("clipPath")
.attr("id", "body-clip")
.append("rect")
.attr("x", 0 - padding)
.attr("y", 0)
.attr("width", quadrantWidth() + 2 * padding)
.attr("height", quadrantHeight());
}
function renderBody(svg) {
if (!_bodyG)
_bodyG = svg.append("g")
.attr("class", "body")
.attr("transform", "translate("
+ xStart() + ","
+ yEnd() + ")") // <-2E
.attr("clip-path", "url(#body-clip)");
renderLines();
renderDots();
}
function renderLines() {
_line = d3.svg.line()
.x(function (d) { return _x(d.x); })
.y(function (d) { return _y(d.y); });
_bodyG.selectAll("path.line")
.data(_data)
.enter()
.append("path")
.style("stroke", function (d, i) {
return _colors(i);
})
.attr("class", "line");
_bodyG.selectAll("path.line")
.data(_data)
.transition()
.attr("d", function (d) { return _line(d); });
}
function renderDots() {
_data.forEach(function (list, i) {
_bodyG.selectAll("circle._" + i)
.data(list)
.enter()
.append("circle")
.attr("class", "dot _" + i)
.on('mouseover', tip.show)
.on('mouseout', tip.hide)
.on('click', function(d, i){
showTotalActivities(d.x);
});
_bodyG.selectAll("circle._" + i)
.data(list)
.style("stroke", function (d) {
return _colors(i); //<-4F
})
.transition() //<-4G
.attr("cx", function (d) {
return _x(d.x); })
.attr("cy", function (d) {
//console.log("dy: " + _y(d.y));
return _y(d.y); })
.attr("r", 4.5);
});
}
function xStart() {
return _margins.left;
}
function yStart() {
return _height - _margins.bottom;
}
function xEnd() {
return _width - _margins.right;
}
function yEnd() {
return _margins.top;
}
function quadrantWidth() {
return _width - _margins.left - _margins.right;
}
function quadrantHeight() {
return _height - _margins.top - _margins.bottom;
}
_chart.width = function (w) {
if (!arguments.length) return _width;
_width = w;
return _chart;
};
_chart.height = function (h) {
if (!arguments.length) return _height;
_height = h;
return _chart;
};
_chart.margins = function (m) {
if (!arguments.length) return _margins;
_margins = m;
return _chart;
};
_chart.colors = function (c) {
if (!arguments.length) return _colors;
_colors = c;
return _chart;
};
_chart.x = function (x) {
if (!arguments.length) return _x;
_x = x;
return _chart;
};
_chart.y = function (y) {
if (!arguments.length) return _y;
_y = y;
return _chart;
};
_chart.addSeries = function (series) {
_data.push(series);
return _chart;
};
_chart.replaceSeries = function (series) {
_data = [];
_data.push(series);
return _chart;
};
return _chart;
}