dataset labels
parent
ad59270a27
commit
d021baf9ce
|
@ -21,6 +21,7 @@ function colorFactory(i) {
|
|||
}
|
||||
|
||||
class Graph {
|
||||
|
||||
view(vnode) {
|
||||
const { title, width, height, margins, datasets} = {...Graph.defaults, ...vnode.attrs};
|
||||
|
||||
|
@ -28,9 +29,9 @@ class Graph {
|
|||
<div class="Graph-container">
|
||||
<svg width="100%" viewBox={`0 0 ${width} ${height}`}>
|
||||
{title && <title>{title}</title>}
|
||||
<rect x="0" y="0" width={width} height={height} fill="none" stroke="#000" stroke-width=".1" />
|
||||
{ /* Bottom margin */ }
|
||||
<line x1={margins[3]} y1={height-margins[2]} x2={width-margins[1]} y2={height-margins[2]} stroke="#000" stroke-width=".1" />
|
||||
|
||||
{ /* Bounding box */}
|
||||
<rect x={margins[3]} y={margins[0]} width={width - margins[1] - margins[3]} height={height - margins[2] - margins[0]} fill="none" stroke-width=".05" stroke="#00000033" />
|
||||
|
||||
{ /* Left margin */ }
|
||||
<line x1={margins[3]} y1={margins[0]} x2={margins[3]} y2={height-margins[2]} stroke="#000" stroke-width=".1" />
|
||||
|
@ -42,15 +43,31 @@ class Graph {
|
|||
if (props.data.length == 0) return;
|
||||
const hasX = props.data[0].length > 1;
|
||||
const minX = props.minX ?? 0;
|
||||
const maxX = props.maxX ?? hasX ? props.data.reduce((p,c) => Math.max(p, c[0]), 0) : props.data.length;
|
||||
const minY = props.minY ?? 0;
|
||||
const maxY = props.maxY ?? props.data.reduce((prev, current) => Math.max(prev, hasX ? current[1] : current[0]), 0);
|
||||
const maxX = props.maxX ?? hasX ? props.data.reduce((p,c) => Math.max(p, c[0]), props.data[0][0]) : props.data.length;
|
||||
const minY = props.minY ?? 0.95 * props.data.reduce((p,c) => Math.min(p, c[0]), props.data[0][(hasX ? 1 : 0)]);
|
||||
const maxY = props.maxY ?? 1.05 * props.data.reduce((prev, current) => Math.max(prev, hasX ? current[1] : current[0]), 0);
|
||||
const tx = translator(minX, minY, maxX, maxY, width, height, ...margins);
|
||||
|
||||
|
||||
const points = props.data.map((datum) => tx(...datum));
|
||||
const line = (<polyline fill="none" stroke={color} stroke-width=".1" points={points.map((v) => v.join(',')).join(' ')} />)
|
||||
return [line, ...points.map(([x,y]) => (<circle cx={x} cy={y} r=".5" fill={color} />))]
|
||||
|
||||
const line = (<polyline fill="none" stroke={color} stroke-width='0.1' points={points.map((v) => v.join(',')).join(' ')} />)
|
||||
const yLabels = (props.yLabels.map((label) => {
|
||||
const yPos = tx(0, label.position)[1];
|
||||
return (
|
||||
<>
|
||||
<text
|
||||
x={margins[3]}
|
||||
y={yPos}
|
||||
dx={-0.25}
|
||||
dy={.5}
|
||||
text-anchor="end"
|
||||
style="font-size:1px; font-weight: normal; text-align: right;"
|
||||
>{label.label}</text>
|
||||
{label.line && <line x1={margins[3]} y1={yPos} x2={width-margins[1]} y2={yPos} stroke-width=".1" stroke="#00000033" />}
|
||||
</>
|
||||
);
|
||||
}));
|
||||
return [line, ...yLabels];
|
||||
|
||||
})}
|
||||
</svg>
|
||||
|
@ -72,6 +89,8 @@ Graph.datasetDefaults = {
|
|||
minX: null,
|
||||
maxX: null,
|
||||
data: [],
|
||||
xLabels: [],
|
||||
yLabels: [],
|
||||
}
|
||||
|
||||
export default Graph;
|
|
@ -1,4 +1,8 @@
|
|||
import m from 'mithril';
|
||||
import CurrentConditions from './views/CurrentConditions';
|
||||
import HistoryView from './views/HistoryView';
|
||||
|
||||
m.mount(document.body, CurrentConditions);
|
||||
m.route(document.body, '/current', {
|
||||
"/current": CurrentConditions,
|
||||
"/history": HistoryView,
|
||||
});
|
|
@ -1,37 +1,58 @@
|
|||
import m from 'mithril';
|
||||
import Layout from '../components/Layout';
|
||||
import Graph from '../components/Graph';
|
||||
import Weather from '../models/weather';
|
||||
|
||||
|
||||
|
||||
const datasets = [
|
||||
{
|
||||
title: "Foo",
|
||||
data: [
|
||||
[0, 1],
|
||||
[1, 2],
|
||||
[2, 4],
|
||||
[3, 5],
|
||||
[4, 4],
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Bar",
|
||||
data: [
|
||||
[0, 2],
|
||||
[1, 3],
|
||||
[2, 10],
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Sin',
|
||||
data: [...Array(100).keys()].map((i) => [i/10, Math.sin(i/10)+1]),
|
||||
function generateDataset({title, field, minY, maxY}) {
|
||||
if (Weather.history.length == 0) return null;
|
||||
return {
|
||||
title: title,
|
||||
data: Weather.history.map((e) => ([e.time, e[field]])),
|
||||
minX: Weather.history[0].time,
|
||||
maxX: Weather.current.time,
|
||||
minY: minY,
|
||||
maxY: maxY
|
||||
}
|
||||
]
|
||||
|
||||
}
|
||||
class HistoryView {
|
||||
view() {
|
||||
const title = 'Recent Conditions';
|
||||
let now = (new Date()).getTime()/1000;
|
||||
const datasets = [
|
||||
//generateDataset({title: "Temperature", field: 'temperature'}),
|
||||
{
|
||||
title: "Temperature",
|
||||
data: [
|
||||
[0, 25],
|
||||
[1, 26],
|
||||
[2, 26.5],
|
||||
[3, 25.9],
|
||||
[4, 24.2],
|
||||
[5, 24.3],
|
||||
[6, 24.1],
|
||||
],
|
||||
yLabels: [
|
||||
{ position: 25, label: '25', line: true},
|
||||
{ position: 20, label: '20'},
|
||||
{ position: 0, label: '0', line: true},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Pressure",
|
||||
data: [
|
||||
[0, 1013],
|
||||
[1, 1013],
|
||||
[2, 1014],
|
||||
[3, 1013],
|
||||
[4, 1012],
|
||||
[5, 1012.5],
|
||||
[6, 1012.2],
|
||||
],
|
||||
minY: 1000,
|
||||
maxY: 1020,
|
||||
}
|
||||
];
|
||||
console.log({datasets});
|
||||
return (
|
||||
<Layout>
|
||||
<h1 class="title">{title}</h1>
|
||||
|
|
Loading…
Reference in New Issue