Nathan Bergey
6 years ago
2 changed files with 155 additions and 91 deletions
-
5src/index.js
-
241src/render.js
@ -1,110 +1,173 @@ |
|||
var d3 = require('d3') |
|||
|
|||
|
|||
export function render(canvas, data) { |
|||
const xWidth = canvas.node().getBoundingClientRect().width |
|||
const yHeight = canvas.node().getBoundingClientRect().height |
|||
const xMargin = 50 |
|||
const yMargin = 25 |
|||
const nElements = data.startTimes.length |
|||
|
|||
const beginTime = new Date( |
|||
data.startTimes[0].getFullYear(), |
|||
data.startTimes[0].getMonth(), |
|||
data.startTimes[0].getDate(), |
|||
0,0,0 |
|||
) |
|||
|
|||
const xRange = d3.scaleTime() |
|||
.domain([beginTime, data.endTimes[nElements - 1]]) |
|||
.range([xMargin, xWidth]) |
|||
const yRange = d3.scaleLinear() |
|||
.domain([-15, 45]) |
|||
.range([yHeight - yMargin, 0]) |
|||
|
|||
const xLine = function (location, style) { |
|||
canvas.append('line') |
|||
.attr('class', style) |
|||
.attr('x1', xMargin) |
|||
.attr('x2', xWidth) |
|||
.attr('y1', yRange(location)) |
|||
.attr('y2', yRange(location)) |
|||
class Chart { |
|||
constructor(canvas, height, width, margin, offset, data, yrange) { |
|||
this.canvas = canvas |
|||
this.height = height |
|||
this.width = width |
|||
this.margin = margin |
|||
this.offset = offset |
|||
this.data = data |
|||
|
|||
this.beginTime = new Date( |
|||
data.startTimes[0].getFullYear(), |
|||
data.startTimes[0].getMonth(), |
|||
data.startTimes[0].getDate(), |
|||
0,0,0 |
|||
) |
|||
this.endTime = data.endTimes[data.endTimes.length - 1] |
|||
this.yRange = d3.scaleLinear() |
|||
.domain(yrange) |
|||
.range([this.height - this.margin.bottom, offset]) |
|||
this.xRange = d3.scaleTime() |
|||
.domain([this.beginTime, this.endTime]) |
|||
.range([margin.left, width]) |
|||
} |
|||
|
|||
draw_yAxisLine() { |
|||
this.canvas.append('line').attr('class', 'axis') |
|||
.attr('x1', this.margin.left).attr('y1', this.offset) |
|||
.attr('x2', this.margin.left).attr('y2', this.height - this.margin.bottom) |
|||
} |
|||
|
|||
draw_xAxisLineTop() { |
|||
this.canvas.append('line').attr('class', 'axis') |
|||
.attr('x1', this.margin.left).attr('y1', this.offset) |
|||
.attr('x2', this.width).attr('y2', this.offset) |
|||
} |
|||
|
|||
draw_xAxisLineBottom() { |
|||
this.canvas.append('line').attr('class', 'axis') |
|||
.attr('x1', this.margin.left).attr('y1', this.height - this.margin.bottom) |
|||
.attr('x2', this.width).attr('y2', this.height - this.margin.bottom) |
|||
} |
|||
|
|||
draw_yAxisTitle(title) { |
|||
const middle = (this.offset + this.height - this.margin.bottom) / 2.0 |
|||
const x = 15 |
|||
this.canvas.append('text').attr('class', 'axis-title') |
|||
.attr('text-anchor', 'middle').attr('dominant-baseline', 'middle') |
|||
.attr('transform', 'rotate(-90,' + x + ',' + middle + ')') |
|||
.attr('x', x).attr('y', middle) |
|||
.text(title) |
|||
} |
|||
|
|||
set_yAxisTic(value, label) { |
|||
this.canvas.append('line').attr('class', 'axis') |
|||
.attr('x1', this.margin.left - 4).attr('y1', this.yRange(value)) |
|||
.attr('x2', this.margin.left).attr('y2', this.yRange(value)) |
|||
this.canvas.append('text').attr('class', 'axis-label') |
|||
.attr('text-anchor', 'end').attr('dominant-baseline', 'middle') |
|||
.attr('x', this.margin.left - 6).attr('y', this.yRange(value)) |
|||
.text(label) |
|||
} |
|||
const yLine = function (date, style) { |
|||
canvas.append('line') |
|||
.attr('class', style) |
|||
.attr('x1', xRange(date)) |
|||
.attr('x2', xRange(date)) |
|||
.attr('y1', 0) |
|||
.attr('y2', yHeight - yMargin) |
|||
|
|||
set_xAxisTic(value, label) { |
|||
this.canvas.append('text').attr('class', 'axis-label') |
|||
.attr('text-anchor', 'middle').attr('dominant-baseline', 'alphabetic') |
|||
.attr('x', this.xRange(value)).attr('y', this.offset - 5) |
|||
.text(label) |
|||
} |
|||
const xAxisLabel = function (date) { |
|||
canvas.append('text') |
|||
.attr('class', 'axis-label') |
|||
.attr('text-anchor', 'middle') |
|||
.attr('dominant-baseline', 'alphabetic') |
|||
.attr('x', xRange(date)) |
|||
.attr('y', yHeight - yMargin + 12) |
|||
.text(date.toLocaleDateString('en-US', {weekday: 'long'})) |
|||
|
|||
draw_yGrid(value, style) { |
|||
this.canvas.append('line').attr('class', style) |
|||
.attr('x1', this.xRange(value)).attr('y1', this.offset) |
|||
.attr('x2', this.xRange(value)).attr('y2', this.height - this.margin.bottom) |
|||
} |
|||
const yAxisLabel = function (value) { |
|||
canvas.append('text') |
|||
.attr('class', 'axis-label') |
|||
.attr('text-anchor', 'end') |
|||
.attr('dominant-baseline', 'middle') |
|||
.attr('x', xMargin - 5) |
|||
.attr('y', yRange(value)) |
|||
.text(value + ' °C') |
|||
|
|||
draw_xGrid(value, style) { |
|||
this.canvas.append('line').attr('class', style) |
|||
.attr('x1', this.margin.left).attr('y1', this.yRange(value)) |
|||
.attr('x2', this.width).attr('y2', this.yRange(value)) |
|||
} |
|||
} |
|||
|
|||
|
|||
/** |
|||
* Sun and moon chart |
|||
*/ |
|||
export function render_astronomy(canvas, height, offset, data) { |
|||
const fullWidth = canvas.node().getBoundingClientRect().width |
|||
const margins = { |
|||
'left': 75, |
|||
'bottom': 10 |
|||
} |
|||
const yrange = [0, 75] |
|||
const chart = new Chart(canvas, height, fullWidth, margins, offset, data, yrange) |
|||
|
|||
chart.draw_yAxisTitle('Altitude') |
|||
chart.set_yAxisTic( 0, '0°') |
|||
chart.set_yAxisTic(45, '45°') |
|||
chart.set_yAxisTic(75, '75°') |
|||
|
|||
const year = chart.beginTime.getFullYear() |
|||
const month = chart.beginTime.getMonth() |
|||
|
|||
for (var day = chart.beginTime.getDate(); day <= chart.endTime.getDate(); day++) { |
|||
const noon = new Date(year, month, day, 12, 0, 0) |
|||
chart.set_xAxisTic(noon, noon.toLocaleDateString('en-US', {weekday: 'long'})) |
|||
chart.draw_yGrid(noon, 'noon') |
|||
|
|||
// Don't draw the first midnight line because that's also our yAxis line
|
|||
if (day != chart.beginTime.getDate()) { |
|||
const midnight = new Date(year, month, day, 0, 0, 0) |
|||
chart.draw_yGrid(midnight, 'midnight') |
|||
} |
|||
} |
|||
|
|||
chart.draw_yAxisLine() |
|||
chart.draw_xAxisLineTop() |
|||
chart.draw_xAxisLineBottom() |
|||
} |
|||
|
|||
|
|||
export function render_temperature(canvas, height, offset, data) { |
|||
const fullWidth = canvas.node().getBoundingClientRect().width |
|||
const margins = { |
|||
'left': 75, |
|||
'bottom': 10 |
|||
} |
|||
const yrange = [-15, 45] |
|||
const chart = new Chart(canvas, height, fullWidth, margins, offset, data, yrange) |
|||
|
|||
const line = d3.line() |
|||
.x(function(d) { return xRange(d.date) }) |
|||
.y(function(d) { return yRange(d.temp) }) |
|||
.x(function(d) { return chart.xRange(d.date) }) |
|||
.y(function(d) { return chart.yRange(d.temp) }) |
|||
.curve(d3.curveBasis) |
|||
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////
|
|||
// Paint
|
|||
chart.draw_yAxisTitle('Temperature') |
|||
chart.set_yAxisTic(-10, '-10 °C') |
|||
chart.draw_xGrid( -10, 'guide') |
|||
chart.set_yAxisTic( 0, '0 °C') |
|||
chart.draw_xGrid( 0, 'zero') |
|||
chart.set_yAxisTic( 12, '12 °C') |
|||
chart.draw_xGrid( 12, 'guide') |
|||
chart.set_yAxisTic( 22, '22 °C') |
|||
chart.draw_xGrid( 22, 'guide') |
|||
chart.set_yAxisTic( 30, '30 °C') |
|||
chart.draw_xGrid( 30, 'hot') |
|||
chart.set_yAxisTic( 40, '40 °C') |
|||
chart.draw_xGrid( 40, 'guide') |
|||
|
|||
yLine(Date.now(), 'now') |
|||
for (let time of data.startTimes) { |
|||
if (time.getHours() === 0) { |
|||
yLine(time, 'midnight') |
|||
} |
|||
if (time.getHours() === 12) { |
|||
yLine(time, 'noon') |
|||
xAxisLabel(time) |
|||
const year = chart.beginTime.getFullYear() |
|||
const month = chart.beginTime.getMonth() |
|||
for (var day = chart.beginTime.getDate(); day <= chart.endTime.getDate(); day++) { |
|||
const noon = new Date(year, month, day, 12, 0, 0) |
|||
chart.draw_yGrid(noon, 'noon') |
|||
// Don't draw the first midnight line because that's also our yAxis line
|
|||
if (day != chart.beginTime.getDate()) { |
|||
const midnight = new Date(year, month, day, 0, 0, 0) |
|||
chart.draw_yGrid(midnight, 'midnight') |
|||
} |
|||
} |
|||
|
|||
xLine(-10, 'guide') |
|||
xLine( 0, 'zero') |
|||
xLine( 12, 'guide') |
|||
xLine( 22, 'guide') |
|||
xLine( 30, 'hot') |
|||
xLine( 40, 'guide') |
|||
yAxisLabel(-10) |
|||
yAxisLabel(0) |
|||
yAxisLabel(12) |
|||
yAxisLabel(22) |
|||
yAxisLabel(30) |
|||
yAxisLabel(40) |
|||
|
|||
canvas.append('path') |
|||
.data([data.temperature]) |
|||
.attr('class', 'data') |
|||
.attr('d', line) |
|||
|
|||
// Axis Lines
|
|||
canvas.append('line') |
|||
.attr('class', 'axis') |
|||
.attr('x1', xMargin) |
|||
.attr('x2', xMargin) |
|||
.attr('y1', 0) |
|||
.attr('y2', yHeight - yMargin) |
|||
canvas.append('line') |
|||
.attr('class', 'axis') |
|||
.attr('x1', xMargin) |
|||
.attr('x2', xWidth) |
|||
.attr('y1', yHeight - yMargin) |
|||
.attr('y2', yHeight - yMargin) |
|||
chart.draw_yAxisLine() |
|||
chart.draw_xAxisLineTop() |
|||
chart.draw_xAxisLineBottom() |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue