Mercurial > personal > weather-server
comparison weather_server/static/script.js @ 13:4eaa9d69c4e2
Extremely basic version of the graph drawer.
| author | Paul Fisher <paul@pfish.zone> |
|---|---|
| date | Sun, 06 Oct 2019 17:09:23 -0400 |
| parents | 9e6289598d8c |
| children |
comparison
equal
deleted
inserted
replaced
| 12:9e6289598d8c | 13:4eaa9d69c4e2 |
|---|---|
| 33 function dewPointC(tempC, rhPct) { | 33 function dewPointC(tempC, rhPct) { |
| 34 const gamma = gammaFn(tempC, rhPct); | 34 const gamma = gammaFn(tempC, rhPct); |
| 35 return MAGNUS_C * gamma / (MAGNUS_B - gamma); | 35 return MAGNUS_C * gamma / (MAGNUS_B - gamma); |
| 36 } | 36 } |
| 37 | 37 |
| 38 const HISTORY_SECONDS = 86400; | |
| 39 | |
| 40 /** | |
| 41 * Sets up everything. | |
| 42 * @param {HTMLElement} tempElement The element where temperature data is. | |
| 43 * @param {HTMLElement} dewPointElement The element where the dew point is. | |
| 44 */ | |
| 45 async function setUp(tempElement, dewPointElement) { | |
| 46 const nowTS = new Date().getTime() / 1000; | |
| 47 const startTS = nowTS - HISTORY_SECONDS; | |
| 48 const query = new URL(location.href); | |
| 49 query.pathname = query.pathname + '/recent'; | |
| 50 query.search = ''; | |
| 51 query.searchParams.set('seconds', String(HISTORY_SECONDS)); | |
| 52 const results = await fetch(query.href); | |
| 53 if (!results.ok) return; | |
| 54 const data = await results.json(); | |
| 55 if (data.length === 0) return; | |
| 56 | |
| 57 const tempsF = data.map(s => [s.sample_time, cToF(s.temp_c)]); | |
| 58 const dewPointsF = data.map( | |
| 59 s => [s.sample_time, cToF(dewPointC(s.temp_c, s.rh_pct))]); | |
| 60 setUpElement(tempElement, [startTS, nowTS], tempsF); | |
| 61 setUpElement(dewPointElement, [startTS, nowTS], dewPointsF); | |
| 62 } | |
| 63 | |
| 64 /** | |
| 65 * Sets up charting for this element. | |
| 66 * @param {HTMLElement} element The element to put a graph in. | |
| 67 * @param {[number, number]} timeRange The `[start, end]` of the time range. | |
| 68 * @param {[number, number][]} data The data to chart. | |
| 69 */ | |
| 70 function setUpElement(element, timeRange, data) { | |
| 71 element.insertBefore(document.createElement('canvas'), element.firstChild); | |
| 72 element.classList.remove('plain'); | |
| 73 element.classList.add('fancy'); | |
| 74 const doDraw = () => redrawCanvas(element, data, timeRange); | |
| 75 doDraw(); | |
| 76 addEventListener('resize', doDraw); | |
| 77 } | |
| 78 | |
| 79 /** | |
| 80 * | |
| 81 * @param {HTMLElement} element The parent element to put the `<canvas>` in. | |
| 82 * @param {[number, number][]} data The data to chart. | |
| 83 * @param {[number, number]} xRange The `[start, end]` of the X range to plot. | |
| 84 */ | |
| 85 function redrawCanvas(element, data, xRange) { | |
| 86 let canvas = element.getElementsByTagName('canvas')[0]; | |
| 87 if (!canvas) { | |
| 88 canvas = document.createElement('canvas'); | |
| 89 element.insertBefore(canvas, element.firstChild); | |
| 90 } | |
| 91 const dpr = window.devicePixelRatio || 1; | |
| 92 const cssSize = element.getBoundingClientRect(); | |
| 93 const pxSize = [cssSize.width * dpr, cssSize.height * dpr]; | |
| 94 canvas.width = pxSize[0]; | |
| 95 canvas.height = pxSize[1]; | |
| 96 const ctx = canvas.getContext('2d'); | |
| 97 ctx.clearRect(0, 0, pxSize[0], pxSize[1]); | |
| 98 const computed = getComputedStyle(element); | |
| 99 ctx.strokeStyle = computed.color; | |
| 100 drawChart(ctx, data, xRange, pxSize); | |
| 101 } | |
| 102 | |
| 38 /** The height of the chart in degrees. */ | 103 /** The height of the chart in degrees. */ |
| 39 const CHART_HEIGHT = 15; | 104 const CHART_RANGE_DEGREES = 15; |
| 40 | 105 |
| 41 /** | 106 /** |
| 42 * Charts some data. | 107 * Charts some data. |
| 43 * | 108 * |
| 44 * @param {CanvasRenderingContext2D} ctx The context to draw in. | 109 * @param {CanvasRenderingContext2D} ctx The context to draw in. |
| 74 | 139 |
| 75 // We want the last value to be, at most, at the top or bottom 1/4 line | 140 // We want the last value to be, at most, at the top or bottom 1/4 line |
| 76 // of the chart. | 141 // of the chart. |
| 77 | 142 |
| 78 // If the middle of the range is already close enough, just use that. | 143 // If the middle of the range is already close enough, just use that. |
| 79 if (CHART_HEIGHT / 4 <= Math.abs(yMid - lastY)) { | 144 if (CHART_RANGE_DEGREES / 4 <= Math.abs(yMid - lastY)) { |
| 80 return [yMid - CHART_HEIGHT / 2, yMid + CHART_HEIGHT / 2]; | 145 return [yMid - CHART_RANGE_DEGREES / 2, yMid + CHART_RANGE_DEGREES / 2]; |
| 81 } | 146 } |
| 82 // Otherwise, clamp the chart range. | 147 // Otherwise, clamp the chart range. |
| 83 if (lastY < yMid) { | 148 if (lastY < yMid) { |
| 84 return [lastY - CHART_HEIGHT / 4, lastY + 3 * CHART_HEIGHT / 4]; | 149 return [lastY - CHART_RANGE_DEGREES / 4, lastY + 3 * CHART_RANGE_DEGREES / 4]; |
| 85 } | 150 } |
| 86 return [lastY - 3 * CHART_HEIGHT / 4, lastY + CHART_HEIGHT / 4]; | 151 return [lastY - 3 * CHART_RANGE_DEGREES / 4, lastY + CHART_RANGE_DEGREES / 4]; |
| 87 } | 152 } |
| 88 | 153 |
| 89 /** | 154 /** |
| 90 * Projects a Cartesian coordinate into Canvas space. | 155 * Projects a Cartesian coordinate into Canvas space. |
| 91 * | 156 * |
