diff --git a/src/data.js b/src/data.js index f543dca..2bed6c5 100644 --- a/src/data.js +++ b/src/data.js @@ -1,50 +1,72 @@ var d3 = require('d3') export function readxml(xmldoc) { - let forcast = xmldoc.childNodes[0] - let data = forcast.children[1] + const forcast = xmldoc.childNodes[0] + const data = forcast.children[1] // Time - let times = data.getElementsByTagName('time-layout')[0] - var startTimes = [] + const times = data.getElementsByTagName('time-layout')[0] + let startTimes = [] for (let time of times.getElementsByTagName('start-valid-time')) { - let date = new Date(time.textContent) + const date = new Date(time.textContent) startTimes.push(date) } - var endTimes = [] + let endTimes = [] for (let time of times.getElementsByTagName('end-valid-time')) { - let date = new Date(time.textContent) + const date = new Date(time.textContent) endTimes.push(date) } // Temperature - var temperatures = [] + let temperatures = [] for (let temp_type of data.getElementsByTagName('temperature')) { if (temp_type.attributes.type.nodeValue === 'hourly') { for (let temp of temp_type.getElementsByTagName('value')) { - let degC = (parseFloat(temp.textContent) - 32) * (5.0/9.0) + const degC = (parseFloat(temp.textContent) - 32) * (5.0/9.0) temperatures.push(degC) } } } + // Cloud Cover + let cloudCover = [] + const clouds = data.getElementsByTagName('cloud-amount')[0] + for (let cloud of clouds.getElementsByTagName('value')) { + cloudCover.push(parseFloat(cloud.textContent)) + } + // Map - let nElements = startTimes.length - var forcastData = [] + const nElements = startTimes.length + + let forcastData = [] + let cloudData = [] + cloudData.push({ + date: startTimes[0], + coverage: 0 + }) for (var i = 0; i < nElements; i++) { - let midtimeScale = d3.scaleTime() + const midtimeScale = d3.scaleTime() .domain([0, 1]) .range([startTimes[i], endTimes[i]]) - let midpointTime = midtimeScale(0.5) + const midpointTime = midtimeScale(0.5) forcastData.push({ - 'date': midpointTime, - 'temp': temperatures[i] + date: midpointTime, + temp: temperatures[i] + }) + cloudData.push({ + date: midpointTime, + coverage: cloudCover[i] }) } + cloudData.push({ + date: endTimes[endTimes.length - 1], + coverage: 0 + }) return { - 'startTimes': startTimes, - 'endTimes': endTimes, - 'temperature': forcastData + startTimes: startTimes, + endTimes: endTimes, + temperature: forcastData, + clouds: cloudData } } diff --git a/src/index.js b/src/index.js index a94145c..f1a47ca 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,6 @@ var d3 = require('d3') import {readxml} from './data.js' -import {render_calendar, render_nights, render_astronomy, render_temperature} from './render.js' +import {render_calendar, render_nights, render_astronomy, render_temperature, render_clouds} from './render.js' const canvas = d3.select('svg') @@ -24,10 +24,16 @@ const render = function (data) { const width = canvas.node().getBoundingClientRect().width const height = canvas.node().getBoundingClientRect().height - render_calendar(canvas, width, 20, 0, data) - render_nights(canvas, width, height - 20, 20, data) - render_astronomy(canvas, width, 70, 20, data) - render_temperature(canvas, width, 350, 70, data) + const calHeight = 20 + const astroHeight = 50 + const tempHeight = 300 + const cloudHeight = height - (calHeight +tempHeight + astroHeight) + + render_calendar(canvas, width, calHeight, 0, data) + render_nights(canvas, width, height - calHeight, calHeight, data) + render_astronomy(canvas, width, astroHeight, calHeight, data) + render_temperature(canvas, width, tempHeight, calHeight + astroHeight, data) + render_clouds(canvas, width, cloudHeight, calHeight + astroHeight + tempHeight, data) } d3.xml(url).then(function(xmldoc) { diff --git a/src/render.js b/src/render.js index 9807dfa..69e3ca1 100644 --- a/src/render.js +++ b/src/render.js @@ -14,9 +14,12 @@ class Chart { this.margin = margin this.data = data + this.top = offset + margin.top + this.bottom = offset + height - margin.bottom + this.yRange = d3.scaleLinear() .domain(yrange) - .range([height - margin.bottom, offset]) + .range([this.bottom, this.top]) this.xRange = d3.scaleTime() .domain([data.beginTime, data.endTime]) .range([margin.left, width - margin.right]) @@ -24,24 +27,24 @@ class Chart { 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) + .attr('x1', this.margin.left).attr('y1', this.top) + .attr('x2', this.margin.left).attr('y2', this.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) + .attr('x1', this.margin.left).attr('y1', this.top) + .attr('x2', this.width - this.margin.right).attr('y2', this.top) } 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) + .attr('x1', this.margin.left).attr('y1', this.bottom) + .attr('x2', this.width - this.margin.right).attr('y2', this.bottom) } draw_yAxisTitle(title) { - const middle = (this.offset + this.height - this.margin.bottom) / 2.0 + const middle = (this.top - this.bottom) / 2.0 const x = 15 this.canvas.append('text').attr('class', 'axis-title') .attr('text-anchor', 'middle').attr('dominant-baseline', 'middle') @@ -63,11 +66,11 @@ class Chart { set_xAxisTic(value, label, anchor) { const x = this.xRange(value) this.canvas.append('line').attr('class', 'axis') - .attr('x1', x).attr('y1', this.height - this.margin.bottom) - .attr('x2', x).attr('y2', this.height - this.margin.bottom + 2) + .attr('x1', x).attr('y1', this.bottom) + .attr('x2', x).attr('y2', this.bottom + 2) this.canvas.append('text').attr('class', 'axis-label') .attr('text-anchor', anchor).attr('dominant-baseline', 'hanging') - .attr('x', x).attr('y', this.height - this.margin.bottom + 1) + .attr('x', x).attr('y', this.bottom + 1) .text(label) } @@ -209,7 +212,7 @@ export function render_astronomy(canvas, width, height, offset, data) { const x = chart.xRange(data.beginTime) const box_width = chart.xRange(data.endTime) - x canvas.append('rect').attr('class', 'blank') - .attr('x', x).attr('y', height - margin.bottom) + .attr('x', x).attr('y', offset + height - margin.bottom) .attr('width', box_width) .attr('height', margin.bottom) @@ -282,7 +285,7 @@ export function render_temperature(canvas, width, height, offset, data) { const margin = { top: 0, left: leftMargin, - bottom: 12, + bottom: 5, right: 0 } const yrange = [-15, 45] @@ -316,3 +319,34 @@ export function render_temperature(canvas, width, height, offset, data) { //chart.draw_xAxisLineTop() chart.draw_xAxisLineBottom() } + +export function render_clouds(canvas, width, height, offset, data) { + const margin = { + top: 0, + left: leftMargin, + bottom: 10, + right: 0 + } + const yrange = [0, 100] + const chart = new Chart(canvas, width, height, offset, margin, data, yrange) + + const line = d3.line() + .x(function(d) { return chart.xRange(d.date) }) + .y(function(d) { return chart.yRange(d.coverage) }) + .curve(d3.curveBasis) + + //chart.draw_xAxisLineTop() + + + chart.set_yAxisTic( 0, '0%') + chart.set_yAxisTic( 50, '50%') + chart.draw_xGrid( 50, 'guide') + chart.set_yAxisTic(100, '100%') + chart.draw_xGrid( 100, 'guide') + + canvas.append('path') + .data([data.clouds]) + .attr('class', 'clouds') + .attr('d', line) + chart.draw_xAxisLineBottom() +} diff --git a/src/style.sass b/src/style.sass index 6fe8c51..bc0eb89 100644 --- a/src/style.sass +++ b/src/style.sass @@ -45,9 +45,6 @@ h1.title path, line fill: none -line - shape-rendering: crispEdges - #calendar .axis stroke: #bbb stroke-width: 1px @@ -74,6 +71,11 @@ path.moon stroke: #999 stroke-width: 1px +path.clouds + opacity: 0.7 + stroke: #bbb + fill: #ddd + line.now stroke: #f5f stroke-width: 1px