Для решения, которое требует минимальных изменений в текущем коде, просто используйте interpolate("step-before")
(или "step-after"
) и измените генератор линии на генератор области:
var line = d3.svg.area()
.x(function (d) { return x(d.x); })
.y1(function (d) { return y(d.y); })
.y0(y(0))
.interpolate("step-before");
Это остается путем, но это выглядит как прямоугольники без отступов между ними. Вот ваш код с этим изменением:
var margin = {
top: 20,
left: 20,
right: 20,
bottom: 20
};
var width = 750 - margin.left - margin.right;
var height = 750 - margin.top - margin.bottom;
var randomDate = function(start, end) {
return new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime()));
};
var data = d3.range(1000).map(function(d) {
return {
x: randomDate(new Date(2015, 0, 1), new Date(2015, 0, 20)),
y: Math.random() * 10
};
}).sort(function(a, b) {
return a.x.getTime() - b.x.getTime();
});
var svg = d3.select('body').append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom);
var g = svg.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
var x = d3.time.scale()
.range([0, width]);
var xAxis = d3.svg.axis()
.scale(x)
.orient('bottom');
var y = d3.scale.linear()
.range([height, 0]);
var yAxis = d3.svg.axis()
.scale(y)
.orient('left');
var line = d3.svg.area()
.x(function(d) {
return x(d.x);
})
.y1(function(d) {
return y(d.y);
})
.y0(y(0))
.interpolate("step-before");
g.append('path')
.attr('class', 'line')
.attr('d', line(data));
g.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + height + ')')
.call(xAxis);
g.append('g')
.attr('class', 'y axis')
.call(yAxis);
var tick = function() {
var minMax = d3.extent(data, function(d) {
return d.x;
});
var duration = 250;
// 1 day offset
var offset = 24 * 60 * 60 * 1000;
var from = minMax[0].getTime();
// 2-days window
var timeWindow = [from, from + 2 * offset];
// Recompute x,y domains
x.domain(timeWindow);
y.domain([0, d3.max(data, function(d) {
return d.y;
})]);
// Redraw the line
g.select('.line')
.attr('d', line(data))
.attr('transform', null);
// Update x axis
g.select('.x.axis')
.transition()
.duration(duration)
.ease('linear')
.call(xAxis);
// Update y axis
g.select('.y.axis')
.transition()
.duration(duration)
.call(yAxis);
//console.log(x(from))
//console.log(x(from + offset));
//console.log(x(from + 2*offset));
// Slide the line to the left
g.select('.line')
.transition()
.duration(duration)
.ease('linear')
.attr('transform', 'translate(' + x(from - duration) + ',0)')
.each('end', function() {
tick();
});
// Remove first point
data.shift();
}
tick();
svg {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.line {
fill: powderblue;
stroke: steelblue;
stroke-width: 1.5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>