d3-line
Version:
D3 line chart
332 lines (244 loc) • 8.59 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _d2 = require('d3');
var _d3 = _interopRequireDefault(_d2);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
// TODO: removal of axis
// TODO: make sure value is included in domain
// TODO: test more values
// TODO: add value updating
// TODO: add value label
// TODO: columns for nicer mouseover
/**
* Default config.
*/
var defaults = {
// target element or selector to contain the svg
target: '#chart',
// value for delta, typically representing the mean of
// the last time period.
value: 0,
// width of chart
width: 550,
// height of chart
height: 150,
// margin
margin: { top: 10, right: 10, bottom: 35, left: 10 },
// axis padding
axisPadding: 10,
// dot radius
dotRadius: 3,
// axis enabled
axis: true,
// axis tick size
tickSize: 10,
// number of x-axis ticks
xTicks: 5,
// nice round values for axis
nice: false,
// transition duration
duration: 300,
// transition easing function
ease: 'linear',
// line interpolation
interpolate: 'cardinal',
// mouseover callback for tooltips or value display
mouseover: function mouseover(_) {},
// mouseout callback for tooltips or value display
mouseout: function mouseout(_) {}
};
/**
* Zeroed margin.
*/
var zeroMargin = { top: 10, right: 10, bottom: 10, left: 10 };
/**
* DeltaLineChart.
*/
var DeltaLineChart = function () {
/**
* Construct with the given `config`.
*/
function DeltaLineChart(config) {
_classCallCheck(this, DeltaLineChart);
this.set(config);
if (!this.axis) this.margin = zeroMargin;
this.init();
}
/**
* Set configuration options.
*/
_createClass(DeltaLineChart, [{
key: 'set',
value: function set(config) {
Object.assign(this, defaults, config);
}
/**
* Dimensions without margin.
*/
}, {
key: 'dimensions',
value: function dimensions() {
var width = this.width;
var height = this.height;
var margin = this.margin;
var w = width - margin.left - margin.right;
var h = height - margin.top - margin.bottom;
return [w, h];
}
/**
* Initialize the chart.
*/
}, {
key: 'init',
value: function init() {
var _this = this;
var target = this.target;
var width = this.width;
var height = this.height;
var margin = this.margin;
var interpolate = this.interpolate;
var axis = this.axis;
var axisPadding = this.axisPadding;
var tickSize = this.tickSize;
var xTicks = this.xTicks;
var _dimensions = this.dimensions();
var _dimensions2 = _slicedToArray(_dimensions, 2);
var w = _dimensions2[0];
var h = _dimensions2[1];
this.chart = _d3.default.select(target).attr('width', width).attr('height', height).append('g').attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')');
this.layer1 = this.chart.append('g');
this.layer2 = this.chart.append('g');
this.x = _d3.default.time.scale().range([0, w]);
this.y = _d3.default.scale.linear().range([h, 0]);
if (axis) {
this.xAxis = _d3.default.svg.axis().orient('bottom').scale(this.x).ticks(xTicks).tickPadding(8).tickSize(tickSize);
this.chart.append('g').attr('class', 'x axis').attr('transform', 'translate(0, ' + (h + axisPadding) + ')').call(this.xAxis);
}
this.line = _d3.default.svg.line().x(function (d) {
return _this.x(d.time);
}).y(function (d) {
return _this.y(d.value);
}).interpolate(interpolate);
this.layer2.append('path').attr('class', 'line');
}
/**
* Prepare domains.
*/
}, {
key: 'prepare',
value: function prepare(data, options) {
var x = this.x;
var y = this.y;
var xAxis = this.xAxis;
var nice = this.nice;
var value = this.value;
var xd = x.domain(_d3.default.extent(data, function (d) {
return d.time;
}));
var yMin = _d3.default.min([value, _d3.default.min(data, function (d) {
return d.value;
})]);
var yMax = _d3.default.max([value, _d3.default.max(data, function (d) {
return d.value;
})]);
var yd = y.domain([yMin, yMax]);
if (nice) {
xd.nice();
yd.nice();
}
}
/**
* Render axis.
*/
}, {
key: 'renderAxis',
value: function renderAxis(data, options) {
var chart = this.chart;
var duration = this.duration;
var ease = this.ease;
var xAxis = this.xAxis;
chart.transition().duration(duration).ease(ease).select('.x.axis').call(xAxis);
}
/**
* Render value line.
*/
}, {
key: 'renderValue',
value: function renderValue(data) {
var layer1 = this.layer1;
var value = this.value;
var x = this.x;
var y = this.y;
var _dimensions3 = this.dimensions();
var _dimensions4 = _slicedToArray(_dimensions3, 2);
var w = _dimensions4[0];
var h = _dimensions4[1];
var v = layer1.selectAll('.value').data([value]);
v.enter().append('line').attr('class', 'value').attr('x1', 0).attr('x2', w);
v.attr('y1', y).attr('y2', y);
}
/**
* Render line.
*/
}, {
key: 'renderLine',
value: function renderLine(data) {
var chart = this.chart;
var layer2 = this.layer2;
var line = this.line;
var x = this.x;
var y = this.y;
var dotRadius = this.dotRadius;
var duration = this.duration;
var ease = this.ease;
var mouseover = this.mouseover;
var mouseout = this.mouseout;
function onmouseover(d) {
mouseover(d);
_d3.default.select(this).transition().duration(300).ease('elastic').attr('r', dotRadius * 2);
}
function onmouseout(d) {
mouseout(d);
_d3.default.select(this).attr('r', dotRadius);
}
chart.transition().duration(duration).ease(ease).select('.line').attr('d', line(data));
var dot = layer2.selectAll('.dot').data(data);
dot.enter().append('circle').attr('class', 'dot').on('mouseover', onmouseover).on('mouseout', onmouseout);
dot.transition().duration(duration).ease(ease).attr('cx', function (d) {
return x(d.time);
}).attr('cy', function (d) {
return y(d.value);
}).attr('r', dotRadius);
dot.exit().remove();
}
/**
* Render the chart against the given `data`.
*/
}, {
key: 'render',
value: function render(data) {
var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
this.prepare(data, options);
if (this.axis) this.renderAxis(data, options);
this.renderValue(data, options);
this.renderLine(data, options);
}
/**
* Update the chart against the given `data`.
*/
}, {
key: 'update',
value: function update(data) {
this.render(data, {
animate: true
});
}
}]);
return DeltaLineChart;
}();
exports.default = DeltaLineChart;