Skip to content

Instantly share code, notes, and snippets.

@tophtucker
Last active December 13, 2016 22:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tophtucker/132ffbfc56fa81f6aa27dd04e1503aa2 to your computer and use it in GitHub Desktop.
Save tophtucker/132ffbfc56fa81f6aa27dd04e1503aa2 to your computer and use it in GitHub Desktop.
time-series-chart.js (d3 v4)
function multiLineChart() {
var margin = {top: 20, right: 20, bottom: 20, left: 20},
width = 760,
height = 120,
xValue = function(d) { return d[0]; },
yValue = function(d) { return d[1]; },
zValue = function(d) { return d; },
xScale = d3.scaleTime(),
yScale = d3.scaleLinear(),
xAxis = d3.axisBottom().scale(xScale).tickSize(6, 0),
line = d3.line().x(X).y(Y),
slope = slopeline().x(X).y(Y);
function chart(selection) {
selection.each(function(data) {
width = this.offsetWidth
height = this.offsetHeight
// Convert data to standard representation greedily;
// this is needed for nondeterministic accessors.
data = zValue(data).map(function(data, index) {
return data.map(function(d, i) {
return [xValue.call(data, d, i), yValue.call(data, d, i)];
});
})
// Update the x-scale.
xScale
.domain(d3.extent(d3.merge(data), function(d) { return d[0]; }))
.range([0, width - margin.left - margin.right]);
// Update the y-scale.
yScale
.domain(d3.extent(d3.merge(data), function(d) { return d[1]; }))
.range([height - margin.top - margin.bottom, 0]);
// Select the svg element, if it exists.
var svg = d3.select(this).selectAll("svg").data([data]);
// Otherwise, create svg element...
var svgEnter = svg.enter().append("svg");
// ...and create the skeletal chart.
var gEnter = svgEnter.append("g");
gEnter.append("g").attr("class", "x axis");
// Merge and update the outer dimensions.
svg = svg.merge(svgEnter)
.attr("width", width)
.attr("height", height);
// Update the inner dimensions.
var g = svg.select("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Update the line path.
var lines = g.selectAll(".line")
.data(data)
lines.enter()
.append("path")
.classed("line", true)
.merge(lines)
.attr("d", line)
// Update the x-axis.
g.select(".x.axis")
.attr("transform", "translate(0," + yScale.range()[0] + ")")
.call(xAxis);
});
}
// The x-accessor for the path generator; xScale ∘ xValue.
function X(d) {
return xScale(d[0]);
}
// The x-accessor for the path generator; yScale ∘ yValue.
function Y(d) {
return yScale(d[1]);
}
chart.margin = function(_) {
if (!arguments.length) return margin;
margin = _;
return chart;
};
chart.width = function(_) {
if (!arguments.length) return width;
width = _;
return chart;
};
chart.height = function(_) {
if (!arguments.length) return height;
height = _;
return chart;
};
chart.x = function(_) {
if (!arguments.length) return xValue;
xValue = _;
return chart;
};
chart.y = function(_) {
if (!arguments.length) return yValue;
yValue = _;
return chart;
};
chart.z = function(_) {
if (!arguments.length) return zValue;
zValue = _;
return chart;
}
return chart;
}
function slopeline() {
var xValue = function(d) { return d[0]; },
yValue = function(d) { return d[1]; }
function line(data) {
var endpoints = [data[0], data[data.length - 1]]
var lineEquation = d => {
var rise = +yValue(endpoints[1]) - yValue(endpoints[0])
var run = +xValue(endpoints[1]) - xValue(endpoints[0])
var slope = rise/run
var intercept = +yValue(endpoints[0]) - slope * xValue(endpoints[0])
return [xValue(d), slope * xValue(d) + intercept]
}
var flattenedData = data.map(lineEquation)
return d3.line()(flattenedData)
}
line.x = function(_) {
if (!arguments.length) return xValue
xValue = _
return line
}
line.y = function(_) {
if (!arguments.length) return yValue
yValue = _
return line
}
return line
}
function timeSeriesChart() {
var margin = {top: 20, right: 20, bottom: 20, left: 20},
width = 760,
height = 120,
xValue = function(d) { return d[0]; },
yValue = function(d) { return d[1]; },
xScale = d3.scaleTime(),
yScale = d3.scaleLinear(),
xAxis = d3.axisBottom().scale(xScale).tickSize(6, 0),
area = d3.area().x(X).y1(Y),
line = d3.line().x(X).y(Y);
function chart(selection) {
selection.each(function(data) {
// Convert data to standard representation greedily;
// this is needed for nondeterministic accessors.
data = data.map(function(d, i) {
return [xValue.call(data, d, i), yValue.call(data, d, i)];
});
// Update the x-scale.
xScale
.domain(d3.extent(data, function(d) { return d[0]; }))
.range([0, width - margin.left - margin.right]);
// Update the y-scale.
yScale
.domain([0, d3.max(data, function(d) { return d[1]; })])
.range([height - margin.top - margin.bottom, 0]);
// Select the svg element, if it exists.
var svg = d3.select(this).selectAll("svg").data([data]);
// Otherwise, create svg element...
var svgEnter = svg.enter().append("svg");
// ...and create the skeletal chart.
var gEnter = svgEnter.append("g");
gEnter.append("path").attr("class", "area");
gEnter.append("path").attr("class", "line");
gEnter.append("g").attr("class", "x axis");
// Merge and update the outer dimensions.
svg = svg.merge(svgEnter)
.attr("width", width)
.attr("height", height);
// Update the inner dimensions.
var g = svg.select("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Update the area path.
g.select(".area")
.attr("d", area.y0(yScale.range()[0]));
// Update the line path.
g.select(".line")
.attr("d", line);
// Update the x-axis.
g.select(".x.axis")
.attr("transform", "translate(0," + yScale.range()[0] + ")")
.call(xAxis);
});
}
// The x-accessor for the path generator; xScale ∘ xValue.
function X(d) {
return xScale(d[0]);
}
// The x-accessor for the path generator; yScale ∘ yValue.
function Y(d) {
return yScale(d[1]);
}
chart.margin = function(_) {
if (!arguments.length) return margin;
margin = _;
return chart;
};
chart.width = function(_) {
if (!arguments.length) return width;
width = _;
return chart;
};
chart.height = function(_) {
if (!arguments.length) return height;
height = _;
return chart;
};
chart.x = function(_) {
if (!arguments.length) return xValue;
xValue = _;
return chart;
};
chart.y = function(_) {
if (!arguments.length) return yValue;
yValue = _;
return chart;
};
return chart;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment