render daily energy graphs
This commit is contained in:
4
client/d3/bar/horizontal.js
vendored
4
client/d3/bar/horizontal.js
vendored
@@ -42,7 +42,7 @@ class HorizontalBarChart extends BarChart {
|
||||
bbox = elem.getBBox(),
|
||||
middleX = bbox.x + (bbox.width / 2),
|
||||
middleY = bbox.y + (bbox.height / 2);
|
||||
return "rotate(-30,"+middleX + "," + middleY+")"
|
||||
return "rotate(-30,"+middleX + "," + middleY+")";
|
||||
});
|
||||
|
||||
bar_chart.x_scale.domain([0, data.max]);
|
||||
@@ -68,7 +68,7 @@ class HorizontalBarChart extends BarChart {
|
||||
.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; })
|
||||
.attr("opacity", function(d) { return d.opacity; });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
11
client/d3/base.js
vendored
11
client/d3/base.js
vendored
@@ -1,3 +1,5 @@
|
||||
import extend from 'extend';
|
||||
|
||||
const DEFAULTS = {
|
||||
outer_width: 500,
|
||||
outer_height: 300,
|
||||
@@ -10,8 +12,9 @@ const DEFAULTS = {
|
||||
domain_attr: undefined,
|
||||
range_attr: undefined,
|
||||
titleize: function(series, datum){
|
||||
var s = datum ? datum.name : series.name,
|
||||
words = s.split(' '),
|
||||
var s = datum ? datum.name : series.title;
|
||||
if (!s) return '';
|
||||
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));
|
||||
@@ -28,7 +31,7 @@ class Chart {
|
||||
|
||||
constructor(options){
|
||||
var chart = this;
|
||||
chart = extend(chart, chart.constructor.DEFAULTS, options);
|
||||
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;
|
||||
@@ -44,4 +47,6 @@ class Chart {
|
||||
|
||||
}
|
||||
|
||||
Chart.DEFAULTS = DEFAULTS;
|
||||
|
||||
export default Chart;
|
||||
|
||||
5
client/d3/chart.scss
Normal file
5
client/d3/chart.scss
Normal file
@@ -0,0 +1,5 @@
|
||||
.d3-chart-axis path {
|
||||
stroke-width: 2;
|
||||
fill: none;
|
||||
stroke:#000000;
|
||||
}
|
||||
152
client/d3/grid/calendar_grid.js
vendored
152
client/d3/grid/calendar_grid.js
vendored
@@ -1,84 +1,104 @@
|
||||
import extend from 'extend';
|
||||
import Chart from './../base';
|
||||
import extend from 'extend';
|
||||
|
||||
// inspired by https://gist.github.com/mbostock/4b66c0d9be9a0d56484e
|
||||
class CalendarGridChart extends Chart{
|
||||
|
||||
get chart_options(){
|
||||
return {
|
||||
grid_padding: 1,
|
||||
var chart = this;
|
||||
return extend(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: 'z',
|
||||
range_attr: undefined,
|
||||
min_range_zero: false,
|
||||
color: '#FFF',
|
||||
extent: []
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
defineAxes(){
|
||||
var grid_chart = this;
|
||||
grid_chart.y_scale = d3.scale.ordinal()
|
||||
.rangeRoundBands([grid_chart.height, 0], 0.05);
|
||||
|
||||
grid_chart.y_axis = d3.svg.axis()
|
||||
.scale(grid_chart.y_scale)
|
||||
.orient("left");
|
||||
// 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()
|
||||
.rangeRoundBands([0, grid_chart.width], 0.05);
|
||||
.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");
|
||||
.orient("top")
|
||||
.outerTickSize(0);
|
||||
|
||||
// append axes
|
||||
grid_chart.svg.append("g")
|
||||
.attr("class", "d3-chart-domain d3-chart-axis");
|
||||
grid_chart.svg.append("g")
|
||||
.attr("class", "d3-chart-range d3-chart-axis")
|
||||
.attr("transform", "translate(0, " + (grid_chart.height - grid_chart.margin.top) + ")");
|
||||
// append x axis
|
||||
grid_chart.svg.append("g").attr("class", "d3-chart-domain d3-chart-axis");
|
||||
}
|
||||
|
||||
afterAxes(){
|
||||
var grid_chart = this;
|
||||
grid_chart.day_length = grid_chart.width / 31 - grid_chart.grid_padding * 30;
|
||||
if (grid_chart.parse_date_format) grid_chart.parseDate = d3.time.format(grid_chart.parse_date_format);
|
||||
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,
|
||||
serialized_data = {
|
||||
series: data
|
||||
};
|
||||
serialized_data.css_class = data.css_class || bar_chart.toClass ? bar_chart.toClass(data_set) : "";
|
||||
serialized_data.title = bar_chart.titleize ? bar_chart.titleize(data_set) : "";
|
||||
var grid_chart = this;
|
||||
data.css_class = data.css_class || grid_chart.toClass ? grid_chart.toClass(data) : "";
|
||||
|
||||
toDate = grid_chart.parseDate ? (d)=>{ return grid_chart.parseDate(d[grid_chart.date_attr]); } : (d)=>{ return d[grid_chart.date_attr] };
|
||||
grid_chart.rangeValue = grid_chart.range_attr ? function(d){ return d[grid_chart.range_attr]; } : grid_chart.rangeValue;
|
||||
|
||||
var min_range = grid_chart.extent[0] || 0,
|
||||
max_range = grid_chart.extent[1] || 0;
|
||||
serialized_data.months = [];
|
||||
series.values.forEach((value)=>{
|
||||
var date = toDate(value),
|
||||
date_s = grid_chart.monthFormat(value);
|
||||
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;
|
||||
|
||||
min_range = Math.min(0, min_range, value[grid_chart.range_attr]);
|
||||
max_range = Math.max(max_range, value[grid_chart.range_attr]);
|
||||
if (serialized_data.months.indexOf(date_s) < 0) serialized_data.months.push(date_s);
|
||||
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();
|
||||
});
|
||||
serialized_data.range ={
|
||||
min: min_range,
|
||||
max: max_range,
|
||||
diff: max_range - min_range };
|
||||
|
||||
serialized_data.months = serialized_data.months.sort((date_s1, date_s2)=>{
|
||||
var date1 = grid_chart.monthFormat(date_s1),
|
||||
date2 = grid_chart.monthFormat(date_s2);
|
||||
return date1.toTime() - date2.toTime();
|
||||
});
|
||||
return serialized_data;
|
||||
return data;
|
||||
};
|
||||
|
||||
drawData(data){
|
||||
@@ -86,35 +106,45 @@ class CalendarGridChart extends Chart{
|
||||
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.x_scale.domain([1, 31]);
|
||||
grid_chart.svg.select(".d3-chart-domain").call(grid_chart.x_axis);
|
||||
|
||||
var grid_units = grid_chart.svg.selectAll(".d3-chart-grid-unit" + series.css_class)
|
||||
.data(data.series.values);
|
||||
grid_chart.applyData(data.series, grid_units.enter().append("rect"));
|
||||
grid_chart.applyData(data.series, grid_units.transition());
|
||||
var grid_units = grid_chart.svg.selectAll(".d3-chart-grid-unit")
|
||||
.data(data.values);
|
||||
grid_chart.applyData(data, grid_units.enter().append("rect"));
|
||||
grid_chart.applyData(data, grid_units.transition());
|
||||
grid_units.exit().remove();
|
||||
}
|
||||
|
||||
// helper method for drawData.
|
||||
applyData(series, elements){
|
||||
applyData(data, elements){
|
||||
var grid_chart = this,
|
||||
series_class = "d3-chart-grid-unit " + series.css_class;
|
||||
series_class = "d3-chart-grid-unit " + data.css_class;
|
||||
elements
|
||||
.attr("class", function(d){ return series_class + " " + d.css_class; })
|
||||
.attr("y", function(d) { return grid_chart.y_scale(grid_chart.monthFormat(d[grid_chart.date_attr])); })
|
||||
.attr("height", grid_chart.y_scale.rangeBand())
|
||||
.attr("x", function(d) { return d[grid_chart.date_attr].getDate(); })
|
||||
.attr("width", function(d) { return grid_chart.x_scale.rangeBand(); })
|
||||
.attr("opacity", function(d) { return grid_chart.applyOpacity(d[grid_chart.range_attr], series.range); })
|
||||
.attr("class", function(d){ return 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.applyOpacity(grid_chart.rangeValue(d), data.range); });
|
||||
}
|
||||
|
||||
applyOpacity(value, range){
|
||||
return (value - range.max) / range.diff;
|
||||
return Math.max(0, Math.min(1, 1 - (range.max - (value - range.min)) / range.diff));
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
10
client/d3/line/spline_stack.js
vendored
10
client/d3/line/spline_stack.js
vendored
@@ -2,7 +2,6 @@ import LineChart from './line';
|
||||
|
||||
const INTERPOLATION = 'cardinal';
|
||||
|
||||
|
||||
// inspired by https://bl.ocks.org/mbostock/3885211
|
||||
class SplineStackChart extends LineChart {
|
||||
|
||||
@@ -28,14 +27,19 @@ class SplineStackChart extends LineChart {
|
||||
spline_stack.defineAxes();
|
||||
}
|
||||
|
||||
get chart_options(){
|
||||
return {
|
||||
interpolation: INTERPOLATION
|
||||
};
|
||||
}
|
||||
|
||||
serializeData(data){
|
||||
var spline_stack = this,
|
||||
serialized_data = {
|
||||
range_min: -Infinity,
|
||||
range_max: Infinity,
|
||||
domain_min: -Infinity,
|
||||
domain_max: Infinity
|
||||
};
|
||||
domain_max: Infinity };
|
||||
|
||||
data.series.forEach(function(series, i){
|
||||
series.css_class = series.css_class || spline_stack.toClass ? spline_stack.toClass(series) : "";
|
||||
|
||||
Reference in New Issue
Block a user