add composite line charts

This commit is contained in:
Eric Hulburd
2016-02-15 18:51:55 -06:00
parent 9ea4a8ebe9
commit 810748d747
3 changed files with 210 additions and 18 deletions

135
client/d3/bar/composite.js vendored Normal file
View File

@@ -0,0 +1,135 @@
import Chart from './../base';
class BarLineChart extends Chart {
get chart_options(){
return Object.assign(Chart.DEFAULTS, {
});
}
afterAxes(){
var chart = this;
line_chart.fnLine = d3.svg.line()
.interpolate(line_chart.chart_options.interpolation)
.x(function(d){ return line_chart.x_scale(d[line_chart.domain_attr]); })
.y(function(d){ return line_chart.y_scale_right(d[line_chart.line_attr]); });
}
defineAxes(){
var chart = this;
// Axes Left
chart.y_scale_left = d3.scale.linear()
.range([chart.height, 0]);
chart.y_axis_left = d3.svg.axis()
.scale(chart.y_scale_left)
.orient("left")
.outerTickSize(0);
// Axes Right
chart.y_scale_right = d3.scale.linear()
.range([chart.height, 0]);
chart.y_axis_left = d3.svg.axis()
.scale(chart.y_scale_right)
.orient("right")
.outerTickSize(0);
chart.x_scale = d3.scale.ordinal()
.rangeRoundBands([chart.height, 0], 0.1);
chart.x_axis = d3.svg.axis()
.scale(chart.x_scale)
.orient("bottom")
.outerTickSize(0)
//chart.x_axis.tickFormat(d3.time.format('%b %d at %H'))
//chart.x_axis.ticks(d3.time.hour, 12);
// append axis groups.
chart.svg.append("g")
.attr("class", "d3-chart-range d3-chart-range-left d3-chart-axis");
chart.svg.append("g")
.attr("class", "d3-chart-range d3-chart-range-right d3-chart-axis");
chart.svg.append("g")
.attr("class", "d3-chart-domain d3-chart-axis")
.attr("transform", "translate(0, " + (chart.height) + ")");
}
defineDomain(domain){
var chart = this;
chart.domain = domain;
chart.x_scale.domain(domain);
chart.svg.select(".d3-chart-domain")
.call(chart.x_axis);
.selectAll("text")
.attr("transform", function(){
var elem = this,
bbox = elem.getBBox(),
middleX = bbox.x + (bbox.width / 2),
middleY = bbox.y + (bbox.height / 2);
return "rotate(-30," + middleX + "," + middleY + ")";
});
}
drawBarData(data){
var chart = this;
data = chart.serializeBarData(data);
chart.y_scale_left.domain(data.range_extent);
chart.svg.select(".d3-chart-range").call(chart.y_axis_left);
data.series.forEach(function(series){
var filtered_values = series.values.filter((value){ return chart.domain.indexOf(value[chart.domain_attr]) < 0; })
bars = chart.svg.selectAll(".d3-chart-bar")
.data(series.values);
chart.applyData(series, bars.enter().append("rect"));
chart.applyData(series, bars.transition());
bars.exit().remove();
});
}
// helper method for drawData
applyBarData(series, elements){
var chart = this,
series_class = "d3-chart-bar " + series.css_class;
elements
.attr("class", function(d){ return series_class + " " + d.css_class; })
.attr("title", function(d){ return d.title; })
.attr("width", chart.x_scale.rangeBand())
.attr("x", chart.x_scale(series.title))
.attr("height", return chart.y_scale(d[chart.bar_attr]))
.attr("y", function(d) { return chart.y_scale(d.cummulative); })
.attr('fill', function(d){ return chart.fnColor(d.title); });
}
drawLineData(data){
var chart = this,
nested_extent = chart.nestedExtent(data.series, 'values', chart.domain_attr, chart.line_attr);
// calibrate axes
bar_chart.y_scale_right.domain([Math.min(0, nested_extent.range_min), nested_extent.range_max]);
bar_chart.svg.select(".d3-chart-range-right")
.call(bar_chart.y_axis_right);
// draw lines
var line = g.selectAll(".d3-chart-line")
.data(data.series);
[line.enter().append('g'), line.transition()].forEach((groups)=>{
line_chart.applyLineData(groups, data.series);
});
line.exit().remove();
}
applyLineData(groups){
var chart = this;
groups
.attr('class', function(series){ return "d3-chart-line " + chart.cssClass(series); })
.attr("title", function(series){ return series.title; })
.append("path")
.attr("d", function(series){ return chart.fnLine(series.values.filter((value)=>{ return chart.domain.indexOf(value[chart.domain_attr]) < 0; })); })
.style("stroke", function(series){ return line_chart.fnColor(series.title); });
}
}

59
client/d3/base.js vendored
View File

@@ -21,7 +21,7 @@ const DEFAULTS = {
}
return array.join(' ');
},
toClass: function(series){
toCssClass: function(series){
return series ? series.title.toLowerCase().replace(/\s+/g, '-') : "";
}
};
@@ -45,6 +45,63 @@ class Chart {
if (chart.afterAxes) chart.afterAxes();
}
defineAxes(){
var chart = this;
chart.y_scale = d3.scale.linear()
.range([chart.height, 0]);
chart.y_axis = d3.svg.axis()
.scale(chart.y_scale)
.orient("left")
.outerTickSize(1);
if (chart.time_series){
chart.x_scale = d3.time.scale()
.range([0, chart.width]);
} else {
chart.x_scale = d3.scale.linear()
.range([0, chart.width]);
}
chart.x_axis = d3.svg.axis()
.scale(chart.x_scale)
.orient("bottom")
.outerTickSize(0)
//chart.x_axis.tickFormat(d3.time.format('%b %d at %H'))
//chart.x_axis.ticks(d3.time.hour, 12);
// append axes
chart.svg.append("g")
.attr("class", "d3-chart-range d3-chart-axis");
chart.svg.append("g")
.attr("class", "d3-chart-domain d3-chart-axis")
.attr("transform", "translate(0, " + (chart.height) + ")");
}
cssClass(series){
var chart = this;
if (!chart.toCssClass) return '';
return chart.toCssClass(series);
}
nestedExtent(a, series_values, domain_attr, range_attr){
var extent = {
min_domain: Infinity,
max_domain: -Infinity,
min_range: Infinity,
max_range: -Infinity
};
a.forEach((series)=>{
series[series_values].forEach((value)=>{
extent.min_domain = Math.min(min_domain, value[domain_attr]);
extent.max_domain = Math.max(max_domain, value[domain_attr]);
extent.min_range = Math.min(min_range, value[range_attr]);
extent.max_range = Math.max(max_range, value[range_attr]);
});
});
returnextent
}
}
Chart.DEFAULTS = DEFAULTS;

View File

@@ -13,36 +13,36 @@ class LineChart extends Chart {
}
defineAxes(){
var line_chart = this;
var chart = this;
line_chart.y_scale = d3.scale.linear()
.range([line_chart.height, 0]);
line_chart.y_axis = d3.svg.axis()
.scale(line_chart.y_scale)
chart.y_scale = d3.scale.linear()
.range([chart.height, 0]);
chart.y_axis = d3.svg.axis()
.scale(chart.y_scale)
.orient("left")
.outerTickSize(1);
if (line_chart.time_series){
line_chart.x_scale = d3.time.scale()
.range([0, line_chart.width]);
if (chart.time_series){
chart.x_scale = d3.time.scale()
.range([0, chart.width]);
} else {
line_chart.x_scale = d3.scale.linear()
.range([0, line_chart.width]);
chart.x_scale = d3.scale.linear()
.range([0, chart.width]);
}
line_chart.x_axis = d3.svg.axis()
.scale(line_chart.x_scale)
chart.x_axis = d3.svg.axis()
.scale(chart.x_scale)
.orient("bottom")
.outerTickSize(0)
//line_chart.x_axis.tickFormat(d3.time.format('%b %d at %H'))
//line_chart.x_axis.ticks(d3.time.hour, 12);
//chart.x_axis.tickFormat(d3.time.format('%b %d at %H'))
//chart.x_axis.ticks(d3.time.hour, 12);
// append axes
line_chart.svg.append("g")
chart.svg.append("g")
.attr("class", "d3-chart-range d3-chart-axis");
line_chart.svg.append("g")
chart.svg.append("g")
.attr("class", "d3-chart-domain d3-chart-axis")
.attr("transform", "translate(0, " + (line_chart.height) + ")");
.attr("transform", "translate(0, " + (chart.height) + ")");
}
afterAxes(){