dont know what happened

This commit is contained in:
Eric Hulburd
2016-02-22 14:36:07 -06:00
parent 0ddae601bd
commit b8d0a9434b
69 changed files with 3711 additions and 0 deletions

48
client/d3/bar/base.js vendored Normal file
View File

@@ -0,0 +1,48 @@
import extend from 'extend';
// This class is inspired by // http://bl.ocks.org/mbostock/3885304.
class BarChart {
get chart_options(){
return {
series_opacity_gradient: true,
margin: {top: 0, left: 70, bottom: 50, right: 20}
};
}
serializeData(data){
var bar_chart = this,
serialized_data = {
max: undefined,
series: []
};
data.forEach(function(data_set){
var series = extend({
css_class: bar_chart.toClass ? bar_chart.toClass(data_set) : "",
title: bar_chart.titleize ? bar_chart.titleize(data_set) : ""
}, data_set);
series.total = 0;
series.values = [];
data_set.values.forEach(function(datum, j){
var series_datum = extend({
name: datum.name,
value: datum.value,
cummulative: series.total,
css_class: bar_chart.toClass ? bar_chart.toClass(data_set, datum) : "",
title: bar_chart.titleize ? bar_chart.titleize(data_set, datum) : "",
opacity: 1.0 - 0.5 * (j / data_set.values.length)
}, datum);
series_datum.series = series;
series.total += datum.value;
series.values.push(series_datum);
});
serialized_data.series.push(series);
serialized_data.max = serialized_data.max === undefined ?
series.total :
Math.max(serialized_data.max, Math.abs(series.total));
});
return serialized_data;
};
}

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); });
}
}

76
client/d3/bar/horizontal.js vendored Normal file
View File

@@ -0,0 +1,76 @@
import BarChart from './bar.base';
class HorizontalBarChart extends BarChart {
defineAxes(){
var bar_chart = this;
bar_chart.y_scale = d3.scale.ordinal()
.rangeRoundBands([bar_chart.height, 0], 0.1);
bar_chart.y_axis = d3.svg.axis()
.scale(bar_chart.y_scale)
.orient("left");
bar_chart.x_scale = d3.scale.linear()
.range([0, bar_chart.width]);
bar_chart.x_axis = d3.svg.axis()
.scale(bar_chart.x_scale)
.orient("bottom")
.ticks(bar_chart.range_ticks)
.outerTickSize(0);
// append axes
bar_chart.svg.append("g")
.attr("class", "d3-chart-domain d3-chart-axis");
bar_chart.svg.append("g")
.attr("class", "d3-chart-range d3-chart-axis")
.attr("transform", "translate(0, " + (bar_chart.height - bar_chart.margin.top) + ")");
}
drawData(data){
var bar_chart = this;
data = bar_chart.serializeData(data);
// calibrate axes
bar_chart.y_scale.domain(data.series.reverse().map(function(d) { return d.name; }));
bar_chart.svg.select(".d3-chart-domain.d3-chart-axis")
.call(bar_chart.y_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+")";
});
bar_chart.x_scale.domain([0, data.max]);
bar_chart.svg.select(".d3-chart-range.d3-chart-axis").call(bar_chart.x_axis);
data.series.forEach(function(series){
var bars = bar_chart.svg.selectAll("d3-chart-rect.d3-chart-bar." + series.css_class)
.data(series.values);
bar_chart.applyData(series, bars.enter().append("rect"));
bar_chart.applyData(series, bars.transition());
bars.exit().remove();
});
}
// helper method for drawData.
applyData(series, elements){
var bar_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("y", function(d) { return bar_chart.y_scale(series.name); })
.attr("height", bar_chart.y_scale.rangeBand())
.attr("x", function(d) { return bar_chart.x_scale(d.cummulative); })
.attr("width", function(d) { return bar_chart.x_scale(d.value); })
.attr("opacity", function(d) { return d.opacity; });
}
}
export default HorizontalBarChart;

76
client/d3/bar/vertical.js vendored Normal file
View File

@@ -0,0 +1,76 @@
import BarChart from './bar.base';
class VerticalBarChart extends BarChart {
defineAxes(){
var bar_chart = this;
bar_chart.y_scale = d3.scale.ordinal()
.rangeRoundBands([bar_chart.height, 0], 0.1);
bar_chart.y_axis = d3.svg.axis()
.scale(bar_chart.y_scale)
.ticks(bar_chart.range_ticks)
.orient("left")
.outerTickSize(0);
bar_chart.x_scale = d3.scale.linear()
.range([0, bar_chart.width]);
bar_chart.x_axis = d3.svg.axis()
.scale(bar_chart.x_scale)
.orient("bottom");
// append axes
bar_chart.svg.append("g")
.attr("class", "d3-chart-range d3-chart-axis");
bar_chart.svg.append("g")
.attr("class", "d3-chart-domain d3-chart-axis")
.attr("transform", "translate(0, " + (bar_chart.height - bar_chart.margin.top) + ")");
}
drawData(data){
var bar_chart = this;
data = bar_chart.serializeData(data);
// calibrate axes
bar_chart.x_scale.domain(data.series.reverse().map((d)=>{ return d.name; }));
bar_chart.svg.select(".d3-chart-domain.d3-chart-axis")
.call(bar_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+")";
});
bar_chart.y_scale.domain([data.min, data.max]);
bar_chart.svg.select(".d3-chart-range.d3-chart-axis").call(bar_chart.y_axis);
data.series.forEach(function(series){
var bars = bar_chart.svg.selectAll(".d3-chart-rect.d3-chart-bar." + series.css_class)
.data(series.values);
bar_chart.applyData(series, bars.enter().append("rect"));
bar_chart.applyData(series, bars.transition());
bars.exit().remove();
});
}
// helper method for drawData
applyData(series, elements){
var bar_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", function(d) { return bar_chart.x_scale.rangeBand(); })
.attr("x", function(d) { return bar_chart.x_scale(series.name); })
.attr("height", return bar_chart.y_scale(d.value))
.attr("y", function(d) { return bar_chart.y_scale(d.cummulative); })
.attr("opacity", function(d) { return d.opacity; });
}
}
export default VerticalBarChart;

75
client/d3/base.js vendored Normal file
View File

@@ -0,0 +1,75 @@
import extend from 'extend';
const DEFAULTS = {
outer_width: 500,
outer_height: 300,
margin: {top: 30, left: 70, bottom: 50, right: 20},
domain_ticks: 10,
range_ticks: 8,
container: "container",
time_series: false,
range_label: undefined,
domain_attr: undefined,
range_attr: undefined,
toCssClass: function(series){
return series ? series.title.toLowerCase().replace(/\s+/g, '-') : "";
}
};
class Chart {
constructor(options){
var chart = this;
chart = extend(chart, chart.chart_options, options);
chart.height = chart.outer_height - chart.margin.top - chart.margin.bottom;
chart.width = chart.outer_width - chart.margin.left - chart.margin.right;
chart.svg = d3.select(chart.container).append("svg")
.attr("width", chart.outer_width)
.attr("height", chart.outer_height)
.append("g")
.attr("transform", "translate(" + chart.margin.left + "," + chart.margin.top + ")");
chart.defineAxes();
if (chart.afterAxes) chart.afterAxes();
}
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]);
});
});
return extent;
}
titleize(s){
var words = s.split(' '),
array = [];
for (var i=0; i<words.length; ++i) {
array.push(words[i].charAt(0).toUpperCase() + words[i].toLowerCase().slice(1));
}
return array.join(' ');
}
}
Chart.DEFAULTS = DEFAULTS;
export default Chart;

5
client/d3/chart.scss Normal file
View File

@@ -0,0 +1,5 @@
.d3-chart-axis path {
stroke-width: 2;
fill: none;
stroke:#000000;
}

153
client/d3/grid/calendar_grid.js vendored Normal file
View File

@@ -0,0 +1,153 @@
import Chart from './../base';
import extend from 'extend';
// inspired by https://gist.github.com/mbostock/4b66c0d9be9a0d56484e
class CalendarGridChart extends Chart{
get chart_options(){
var chart = this;
return extend(Object.assign({}, Chart.DEFAULTS), {
margin: {top: 30, left: 150, bottom: 0, right: 0},
grid_padding: 0.05,
parse_date_format: '%Y-%m-%d',
display_date_format: '%B %Y',
date_attr: 'date',
range_attr: undefined,
min_range_zero: false,
color: '#FFF',
extent: []
})
}
defineAxes(){
var grid_chart = this;
// y scale is dependent on number of months.
grid_chart.y_axis = d3.svg.axis().orient("left").outerTickSize(0);
grid_chart.y_scale = d3.scale.ordinal()
grid_chart.svg.append("g")
.attr("class", "d3-chart-range d3-chart-axis");
grid_chart.x_scale = d3.scale.ordinal()
.domain(d3.range(31).map((n)=>{ return n+1; }))
.rangeRoundBands([0, grid_chart.width], grid_chart.grid_padding, 0);
grid_chart.x_axis = d3.svg.axis()
.scale(grid_chart.x_scale)
.orient("top")
.outerTickSize(0);
// append x axis
grid_chart.svg.append("g").attr("class", "d3-chart-domain d3-chart-axis");
}
afterAxes(){
var grid_chart = this;
grid_chart.grid_unit_size = grid_chart.width / 31 - grid_chart.grid_padding * grid_chart.width / 30;
if (grid_chart.display_date_format) grid_chart.displayDate = d3.time.format(grid_chart.display_date_format);
if (!grid_chart.toDate && grid_chart.parse_date_format){
grid_chart.parseDate = d3.time.format(grid_chart.parse_date_format);
grid_chart.toDate = (datum)=>{
grid_chart.parseDate(datum[grid_chart.date_attr]);
}
} else if (!grid_chart.toDate){
grid_chart.toDate = (datum)=>{ return datum[grid_chart.date_attr] };
}
grid_chart.monthFormat = d3.time.format('%B %Y');
grid_chart.toMonthString = (datum)=>{
return grid_chart.monthFormat(grid_chart.toDate(datum));
}
}
serializeData(data){
var grid_chart = this;
data.css_class = data.css_class || grid_chart.toClass ? grid_chart.toClass(data) : "";
grid_chart.rangeValue = grid_chart.range_attr ? function(d){ return d[grid_chart.range_attr]; } : grid_chart.rangeValue;
data.months = [];
if (data.min_range !== undefined && data.max_range !== undefined){
data.range = {min: data.min_range, max: data.max_range};
data.values.forEach((value)=>{
var date = grid_chart.toDate(value),
date_s = grid_chart.monthFormat(date);
if (data.months.indexOf(date_s) < 0) data.months.push(date_s);
});
} else {
var min_range = Infinity,
max_range = -Infinity;
data.values.forEach((value)=>{
var date = grid_chart.toDate(value),
date_s = grid_chart.monthFormat(date),
range_value =grid_chart.rangeValue(value);
min_range = Math.min(min_range, range_value);
max_range = Math.max(max_range, range_value);
if (data.months.indexOf(date_s) < 0) data.months.push(date_s);
});
if (grid_chart.min_range_zero) min_range = Math.min(min_range, 0);
data.range = { min: min_range, max: max_range };
}
data.range.diff = data.range.max - data.range.min;
data.months = data.months.sort((date_s1, date_s2)=>{
var date1 = grid_chart.monthFormat.parse(date_s1),
date2 = grid_chart.monthFormat.parse(date_s2);
return date1.getTime() - date2.getTime();
});
return data;
};
drawData(data){
var grid_chart = this;
grid_chart.i = grid_chart.i || 1;
data = grid_chart.serializeData(data);
// calibrate axes
var y_axis_height = grid_chart.grid_unit_size * (1 + grid_chart.grid_padding) * data.months.length;
grid_chart.y_scale.rangeRoundBands([0, y_axis_height], grid_chart.grid_padding, 0);
grid_chart.y_scale.domain(data.months);
grid_chart.y_axis.scale(grid_chart.y_scale);
grid_chart.svg.select(".d3-chart-range")
.call(grid_chart.y_axis);
grid_chart.svg.select(".d3-chart-domain").call(grid_chart.x_axis);
var grid_units = grid_chart.svg.selectAll(".d3-chart-grid-unit")
.data(data.values);
grid_units.exit().remove();
grid_chart.applyData(data, grid_units.enter().append("rect"));
grid_chart.applyData(data, grid_units);
}
// helper method for drawData.
applyData(data, elements){
var grid_chart = this,
series_class = "d3-chart-grid-unit " + data.css_class;
elements
.attr("class", series_class)
.attr("y", function(d) {
var bottom = grid_chart.y_scale(grid_chart.toMonthString(d)),
middle = grid_chart.y_scale.rangeBand() / 2 - grid_chart.grid_unit_size / 2;
return bottom + middle;
})
.attr("height", grid_chart.grid_unit_size)
.attr("x", function(d) {
return grid_chart.x_scale(grid_chart.toDate(d).getDate());
})
.attr("width", function(d) { return grid_chart.grid_unit_size; })
.attr('fill', grid_chart.color)
.attr("opacity", function(d) { return grid_chart.calculateOpacity(75, data.range); });
}
calculateOpacity(value, range){
return Math.max(0, Math.min(1, 1 - (range.max - (value - range.min)) / range.diff));
};
}
export default CalendarGridChart;

122
client/d3/line/line.js vendored Normal file
View File

@@ -0,0 +1,122 @@
import extend from 'extend';
import Chart from './../base';
// inspired by https://gist.github.com/mbostock/4b66c0d9be9a0d56484e
class LineChart extends Chart {
get chart_options(){
return {
interpolation: 'basis'
};
}
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) + ")");
}
afterAxes(){
var line_chart = this;
// function that draws the lines.
line_chart.line = 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(d[line_chart.range_attr]); });
// function that returns unique color based on series_title.
line_chart.color = d3.scale.category20();
}
serializeData(data){
var line_chart = this,
serialized_data = {
series: [],
range_min: Infinity,
range_max: -Infinity,
domain_min: Infinity,
domain_max: -Infinity,
};
data.forEach(function(data_set){
var series = extend({
css_class: line_chart.toClass ? line_chart.toClass(data_set) : "",
title: line_chart.titleize ? line_chart.titleize(data_set) : "",
color: ''
}, data_set);
series.values.forEach((value)=>{
series_data.range_min = Math.min(series_data.range_min, value[line_chart.range_attr]);
series_data.range_max = Math.max(series_data.range_max, value[line_chart.range_attr]);
series_data.domain_min = Math.min(series_data.domain_min, value[line_chart.domain_attr]);
series_data.domain_max = Math.max(series_data.domain_max, value[line_chart.domain_attr]);
});
serialized_data.series.push(series);
});
return serialized_data;
};
drawData(data){
var line_chart = this;
data = line_chart.serialize_data;
// calibrate axes
bar_chart.y_scale.domain([Math.min(0, data.range_min), data.range_max]);
bar_chart.svg.select(".d3-chart-range.d3-chart-axis")
.call(bar_chart.y_axis);
bar_chart.x_scale.domain([data.domain_max, Math.min(data.domain_min)]);
bar_chart.svg.select(".d3-chart-domain.d3-chart-axis").call(bar_chart.x_axis);
// draw lines
var line = g.selectAll(".d3-chart-series")
.data(data.series);
[line.enter().append('g'), line.transition()].forEach((groups)=>{
line_chart.applyData(groups);
});
line.exit().remove();
}
applyData(groups){
var line_chart = this;
groups
.attr('class', function(series){ return "d3-chart-line " + series.css_class; })
.attr("title", function(series){ return series.title; })
.append("path")
.attr("d", function(series){ return line_chart.line(series.values); })
.style("stroke", function(series){ return line_chart.color(series.title); });
}
}
export default LineChart;

13
client/d3/line/spline.js vendored Normal file
View File

@@ -0,0 +1,13 @@
import LineChart from './line';
const INTEPOLATION = 'cardinal';
class SplineChart extends LineChart {
get chart_options(){
return {
interpolation: INTEPOLATION
}
}
}

108
client/d3/line/spline_stack.js vendored Normal file
View File

@@ -0,0 +1,108 @@
import LineChart from './line';
const INTERPOLATION = 'cardinal';
// inspired by https://bl.ocks.org/mbostock/3885211
class SplineStackChart extends LineChart {
get chart_options(){
return Object.assign(Object.assign({}, LineChart.DEFAULTS), {
interpolation: INTERPOLATION
});
}
afterAxes(){
var spline_stack = this;
spline_stack.fnArea = d3.svg.area()
.x(function(d, i) { return spline_stack.x_scale(d.x); })
.y0(function(d) { return spline_stack.y_scale(d.y0); })
.y1(function(d) { return spline_stack.y_scale(d.y0 + d.y); })
.interpolate(spline_stack.interpolation);
spline_stack.fnStack = d3.layout.stack()
.values(function(d) { return d.values; });
// function that returns unique color based on series_title.
spline_stack.fnColor = d3.scale.category20();
}
serializeData(data){
var spline_stack = this,
serialized_data = {
series: [] };
data.series.forEach(function(series, i){
series.css_class = series.css_class || spline_stack.toClass ? spline_stack.toClass(series) : "series-" + i;
if (spline_stack.domain_attr !== 'x' && spline_stack.range_attr !== 'y'){
series.values = series.values.map((value)=>{
return {x: value[spline_stack.domain_attr], y: value[spline_stack.range_attr], series: series};
});
}
serialized_data.series.push(series);
});
serialized_data.series = spline_stack.fnStack(serialized_data.series);
// assume all series have same domain, use first series to establish extent.
serialized_data.domain_extent = d3.extent(serialized_data.series[0].values.map((value)=>{ return value.x; }));
// final series will have the highest y values.
serialized_data.range_max = d3.max(serialized_data.series[serialized_data.series.length - 1].values.map((value)=>{ return value.y0 + value.y; }))
return serialized_data;
};
drawData(data){
var spline_stack = this;
data = spline_stack.serializeData(data);
// calibrate axes.
spline_stack.y_scale.domain([0, data.range_max]);
spline_stack.svg.select(".d3-chart-range.d3-chart-axis")
.call(spline_stack.y_axis);
spline_stack.x_scale.domain(data.domain_extent);
spline_stack.svg.select(".d3-chart-domain.d3-chart-axis").call(spline_stack.x_axis);
var stack = spline_stack.svg.selectAll(".d3-chart-spline-stack")
.data(data.series);
[stack.enter().append("path"), stack].forEach((paths)=>{
spline_stack.applyData(paths);
});
stack.exit().remove();
if (spline_stack.include_dots){
data.series.forEach((series)=>{
var dots = spline_stack.svg.selectAll(".d3-chart-spline-dot." + series.css_class)
.data(series.values);
[dots.enter().append("circle"), dots].forEach((circles)=>{
spline_stack.applyDots(series, circles);
});
dots.exit().remove();
});
}
}
applyData(paths){
var spline_stack = this;
paths
.attr("class", function(series){ return "d3-chart-spline-stack " + series.css_class;})
.attr("d", function(series){ return spline_stack.fnArea(series.values); })
.style("fill", function(series){ return spline_stack.fnColor(series.title); })
.attr('opacity', 1);
}
applyDots(series, circles){
var spline_stack = this;
circles
.attr('class', 'd3-chart-spline-dot ' + series.css_class)
.attr("r", 2)
.attr("cx", function(d, i){ return spline_stack.x_scale(d.x); })
.attr("cy", function(d, i){ return spline_stack.y_scale(d.y + d.y0); })
.attr("title", function(d, i){ return spline_stack.titleizeDatum(series, d); })
.style("fill", spline_stack.fnColor(series.title))
.attr('opacity', 1)
.attr('stroke-width', 0)
.attr('stroke', '#fff');
}
}
export default SplineStackChart;

133
client/d3/sliders/date_range.js vendored Normal file
View File

@@ -0,0 +1,133 @@
import Chart from './../base';
class DateRange extends Chart {
get chart_options(){
return Object.assign(Object.assign({}, Chart.DEFAULTS), {
outer_width: 600,
outer_height: 250,
margin: {top: 20, left: 10, bottom: 20, right: 10},
});
}
defineAxes(){
var date_range = this;
date_range.x_scale = d3.time.scale()
.range([0, date_range.width])
.clamp(true);
date_range.x_axis = d3.svg.axis()
.scale(date_range.x_scale)
.orient("bottom")
.ticks(d3.time.weeks, 1)
//.tickFormat(function(d) { return d + "°"; })
.tickSize(1)
.outerTickSize(1)
.tickPadding(12)
date_range.svg.append("g")
.attr("class", "d3-chart-domain")
.attr("transform", "translate(0," + date_range.height / 2 + ")");
}
afterAxes(){
var date_range = this;
date_range.slider = date_range.svg.append("g")
.attr("class", "d3-chart-slider");
date_range.min_handle = date_range.slider.append("circle")
.attr("class", "d3-chart-min-handle")
.attr("transform", "translate(0," + date_range.height / 2 + ")")
.attr("r", 9);
date_range.max_handle = date_range.slider.append("circle")
.attr("class", "d3-chart-max-handle")
.attr("transform", "translate(0," + date_range.height / 2 + ")")
.attr("r", 9);
date_range.brush = d3.svg.brush()
.x(date_range.x_scale);
date_range.slider
.call(date_range.brush)
//.select(".background")
// .attr("height", date_range.height);
date_range.slider.call(date_range.brush)
.selectAll(".extent,.resize")
.remove();
}
drawData(data){
var date_range = this;
date_range.x_scale.domain([data.abs_min, data.abs_max]);
date_range.svg.select(".d3-chart-domain")
.call(date_range.x_axis);
date_range.min_handle.attr('cx', date_range.x_scale(data.current_min));
date_range.max_handle.attr('cx', date_range.x_scale(data.current_max));
date_range.brush.extent([data.current_min, data.current_min])
.on("brush", ()=>{
DateRange.handleBrush(date_range, eval('this'));
});
date_range.slider
.call(date_range.brush.event)
.transition() // gratuitous intro!
.duration(750)
.call(date_range.brush.extent([data.current_min, data.current_min]))
.call(date_range.brush.event);
}
static handleBrush(date_range, elem){
var date = date_range.brush.extent()[0],
current_min = parseInt(date_range.min_handle.attr('cx')),
current_max = parseInt(date_range.max_handle.attr('cx'));
if (!current_min && !current_max) return false
if (d3.event.sourceEvent) { // not a programmatic event
date = date_range.x_scale.invert(d3.mouse(elem)[0]);
date_range.brush.extent([date, date]);
}
var value = date_range.x_scale(date);
if (value < current_max && value > current_min){
if (Math.abs(value - current_min) < Math.abs(value - current_max)){
date_range.min_handle.attr('cx', value);
current_min = value;
} else {
date_range.max_handle.attr('cx', value);
current_max = value;
}
} else if (value >= current_max){
date_range.max_handle.attr('cx', value);
current_max = value;
if (d3.event.sourceEvent && date_range.maxDelta){
var new_current_min = date_range.maxDelta(date, date_range.x_scale.invert(current_min));
if (new_current_min) date_range.min_handle.attr('cx', date_range.x_scale(new_current_min));
}
} else {
date_range.min_handle.attr('cx', value);
current_min = value;
if (d3.event.sourceEvent && date_range.maxDelta){
var new_current_max = date_range.maxDelta(date, date_range.x_scale.invert(current_max));
if (new_current_max) date_range.max_handle.attr('cx', date_range.x_scale(new_current_max));
}
}
if (d3.event.sourceEvent && date_range.onRangeUpdated) {
date_range.onRangeUpdated(date_range.x_scale.invert(current_min), date_range.x_scale.invert(current_max));
}
}
}
export default DateRange;