Last active
April 2, 2018 11:28
-
-
Save pbeshai/b2c4ae410c4ea498a8bbe8ad33bce64e to your computer and use it in GitHub Desktop.
Helpers for Showing Missing Data in Line Charts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Helper function to compute the contiguous segments of the data | |
* | |
* Derived from https://github.com/pbeshai/d3-line-chunked/blob/master/src/lineChunked.js | |
* | |
* @param {Array} lineData the line data | |
* @param {Function} defined function that takes a data point and returns true if | |
* it is defined, false otherwise | |
* @param {Function} isNext function that takes the previous data point and the | |
* current one and returns true if the current point is the expected one to | |
* follow the previous, false otherwise. | |
* @return {Array} An array of segments (subarrays) of the line data | |
*/ | |
function computeSegments(lineData, defined, isNext) { | |
defined = defined || function (d) { return true; }; | |
isNext = isNext || function (prev, curr) { return true; }; | |
var startNewSegment = true; | |
// split into segments of continuous data | |
var segments = lineData.reduce(function (segments, d) { | |
// skip if this point has no data | |
if (!defined(d)) { | |
startNewSegment = true; | |
return segments; | |
} | |
// if we are starting a new segment, start it with this point | |
if (startNewSegment) { | |
segments.push([d]); | |
startNewSegment = false; | |
// otherwise see if we are adding to the last segment | |
} else { | |
var lastSegment = segments[segments.length - 1]; | |
var lastDatum = lastSegment[lastSegment.length - 1]; | |
// if we expect this point to come next, add it to the segment | |
if (isNext(lastDatum, d)) { | |
lastSegment.push(d); | |
// otherwise create a new segment | |
} else { | |
segments.push([d]); | |
} | |
} | |
return segments; | |
}, []); | |
return segments; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Compute the gaps from segments. Takes an array of segments and creates new segments | |
* based on the edges of adjacent segments. | |
* | |
* @param {Array} segments The segments array (e.g. from computeSegments) | |
* @return {Array} gaps The gaps array (same form as segments, but representing spaces between segments) | |
*/ | |
function gapsFromSegments(segments) { | |
const gaps = []; | |
for (var i = 0; i < segments.length - 1; i++) { | |
const currSegment = segments[i]; | |
const nextSegment = segments[i + 1]; | |
gaps.push([currSegment[currSegment.length - 1], nextSegment[0]]) | |
} | |
return gaps; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Create the data for the gradient stops from the segments | |
* @param {Array} segments The segments array (e.g. from computeSegments) | |
* @param {Array} xDomain The xDomain that the path is created over. | |
* Used to map to 0 to 100% for the gradient stops. Uses linear scale. | |
* @return {Array} The stops data | |
*/ | |
function stopsFromSegments(segments, xDomain) { | |
var gradientScale = d3.scaleLinear().domain(xDomain).range([0, 100]).clamp(true); | |
var stops = segments.reduce(function (stops, segment) { | |
// get first and last points from the segments | |
var first = segment[0]; | |
var last = segment[segment.length - 1]; | |
// add gap-segment segment-gap stops (4) | |
stops.push({ type: 'gap', offset: gradientScale(first[0]) + '%' }); | |
stops.push({ type: 'segment', offset: gradientScale(first[0]) + '%' }); | |
stops.push({ type: 'segment', offset: gradientScale(last[0]) + '%' }); | |
stops.push({ type: 'gap', offset: gradientScale(last[0]) + '%' }); | |
return stops; | |
}, []); | |
return stops; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment