Browse Source

circular gauge rendering (wip)

master
Youen Toupin 3 years ago
parent
commit
03d8fa6771
  1. 0
      WebApp/src/components/widgets/gauge-circular.css
  2. 81
      WebApp/src/components/widgets/gauge-circular.tsx
  3. 15
      WebApp/src/components/widgets/gauge.css
  4. 10
      WebApp/src/components/widgets/widget.css
  5. 9
      WebApp/src/pages/dashboard/dashboard-page.css
  6. 3
      WebApp/src/pages/dashboard/dashboard-page.tsx

0
WebApp/src/components/widgets/gauge-circular.css

81
WebApp/src/components/widgets/gauge-circular.tsx

@ -0,0 +1,81 @@
import m from 'mithril';
import { Gauge } from 'components/widgets/gauge';
import { Pipe } from 'utilities/pipe';
require('./gauge-circular.css');
export class GaugeCircular extends Gauge {
constructor(vnode: any) {
super(vnode);
}
createSvg(svgElement: SVGElement) {
let w = Math.round(svgElement.clientWidth);
let h = Math.round(svgElement.clientHeight);
svgElement.setAttribute('viewBox', "0 0 "+w+" "+h);
let svgRound = (v: number) => Math.round(v * 100.0) / 100.0;
const arcRatio = 0.75; // from 0.5 for half circle to 1.0 for full circle
const gaugeWidthRatio = 0.15; // relative to the smallest dimension of the drawing area
const lineThickness = 1;
let gaugeWidth = Math.round(Math.min(w, h) * gaugeWidthRatio);
let gaugeRadius = Math.round(Math.min(w, h) * 0.5 - gaugeWidth * 0.5 - lineThickness - 1);
let cx = Math.round(w * 0.5); let cy = Math.round(h * 0.5);
let openingHalfAngle = Math.PI * (1.0 - arcRatio);
let arcLength = Math.PI * 2.0 * gaugeRadius * arcRatio;
let startx = svgRound(cx - Math.sin(openingHalfAngle) * gaugeRadius);
let starty = svgRound(cy + Math.cos(openingHalfAngle) * gaugeRadius);
let dx = svgRound(2.0 * Math.sin(openingHalfAngle) * gaugeRadius);
let outlineArcRatio = (arcLength + lineThickness*2.0) / (Math.PI * 2.0 * gaugeRadius);
let outlineOpeningHalfAngle = Math.PI * (1.0 - outlineArcRatio);
let outlineStartx = svgRound(cx - Math.sin(outlineOpeningHalfAngle) * gaugeRadius);
let outlineStarty = svgRound(cy + Math.cos(outlineOpeningHalfAngle) * gaugeRadius);
let outlineDx = svgRound(2.0 * Math.sin(outlineOpeningHalfAngle) * gaugeRadius);
let bgOutline = document.createElementNS('http://www.w3.org/2000/svg', 'path');
bgOutline.setAttribute('d', 'M'+outlineStartx+' '+outlineStarty+' a'+gaugeRadius+' '+gaugeRadius+' 0 1 1 '+outlineDx+' 0');
bgOutline.setAttribute('style', 'stroke-width: '+(gaugeWidth+lineThickness*2));
bgOutline.classList.add('gauge-bg-outline');
svgElement.append(bgOutline);
let bg = document.createElementNS('http://www.w3.org/2000/svg', 'path');
bg.setAttribute('d', 'M'+startx+' '+starty+' a'+gaugeRadius+' '+gaugeRadius+' 0 1 1 '+dx+' 0');
bg.setAttribute('style', 'stroke-width: '+(gaugeWidth));
bg.classList.add('gauge-bg');
svgElement.append(bg);
let barHeight = 15;
const barGap = barHeight * 0.2;
let numBars = Math.round(h / (barHeight + barGap));
let bh = (h - (numBars+1)*barGap) / numBars;
barHeight = Math.round(bh);
/*for(let barIdx = 0; barIdx < numBars; ++barIdx) {
let bar = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
bar.setAttribute('width', (w - barGap * 2).toString());
bar.setAttribute('height', barHeight.toString());
bar.classList.add('gauge-bar');
bar.classList.toggle('lit', false);
bar.setAttribute('x', barGap.toString());
bar.setAttribute('y', (h - barIdx * (bh+barGap) - barGap - barHeight).toString());
svgElement.append(bar);
this.bars.push(bar);
}*/
}
oncreate(vnode: any) {
let svgElement: SVGElement = vnode.dom.querySelector('svg');
this.createSvg(svgElement);
super.oncreate(vnode);
}
}

15
WebApp/src/components/widgets/gauge.css

@ -1,6 +1,11 @@
div.gauge { div.gauge {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
text-align: center;
}
div.gauge svg {
flex: 1;
} }
div.gauge span.integral-value { div.gauge span.integral-value {
@ -23,6 +28,16 @@ rect.gauge-bg {
stroke: rgb(0,0,0) stroke: rgb(0,0,0)
} }
path.gauge-bg-outline {
stroke: rgb(0,0,0);
fill: none;
}
path.gauge-bg {
stroke: rgb(255,255,255);
fill: none;
}
rect.gauge-bar { rect.gauge-bar {
fill: rgb(230,230,230); fill: rgb(230,230,230);
stroke-width: 1; stroke-width: 1;

10
WebApp/src/components/widgets/widget.css

@ -1,3 +1,11 @@
div.widget svg { div.widgets-row {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
display: flex;
flex-direction: row;
}
div.widget {
flex: 1; flex: 1;
margin: 0.2rem;
} }

9
WebApp/src/pages/dashboard/dashboard-page.css

@ -2,12 +2,3 @@ div.dashboard-page {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
div.widgets-row {
display: flex;
flex-direction: row;
}
div.widget {
flex: 1;
}

3
WebApp/src/pages/dashboard/dashboard-page.tsx

@ -5,6 +5,7 @@ import { Pipe } from 'utilities/pipe';
import { Clock } from 'components/widgets/clock'; import { Clock } from 'components/widgets/clock';
import { GaugeLinear } from 'components/widgets/gauge-linear'; import { GaugeLinear } from 'components/widgets/gauge-linear';
import { GaugeCircular } from 'components/widgets/gauge-circular';
require('./dashboard-page.css'); require('./dashboard-page.css');
@ -52,7 +53,7 @@ export class DashboardPage extends Page {
</div> </div>
<div class="widgets-row" style="height: 40%"> <div class="widgets-row" style="height: 40%">
<GaugeLinear widgetWidth={0.2} gaugeValue={this.power} gaugeMaxValue={999.0} unit="W" /> <GaugeLinear widgetWidth={0.2} gaugeValue={this.power} gaugeMaxValue={999.0} unit="W" />
<GaugeLinear widgetWidth={0.6} gaugeValue={this.speed} gaugeMaxValue={50.0} decimals={1} unit="km/h" /> <GaugeCircular widgetWidth={0.6} gaugeValue={this.speed} gaugeMaxValue={50.0} decimals={1} unit="km/h" />
<GaugeLinear widgetWidth={0.2} gaugeValue={this.battery} gaugeMaxValue={100.0} unit="%" /> <GaugeLinear widgetWidth={0.2} gaugeValue={this.battery} gaugeMaxValue={100.0} unit="%" />
</div> </div>
</div> </div>

Loading…
Cancel
Save