circular gauge rendering (wip)
This commit is contained in:
parent
b8bec376a0
commit
03d8fa6771
0
WebApp/src/components/widgets/gauge-circular.css
Normal file
0
WebApp/src/components/widgets/gauge-circular.css
Normal file
81
WebApp/src/components/widgets/gauge-circular.tsx
Normal file
81
WebApp/src/components/widgets/gauge-circular.tsx
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
@ -1,3 +1,11 @@
|
|||||||
div.widget svg {
|
div.widgets-row {
|
||||||
flex: 1;
|
padding-top: 0.5rem;
|
||||||
|
padding-bottom: 0.5rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.widget {
|
||||||
|
flex: 1;
|
||||||
|
margin: 0.2rem;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
|
@ -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…
Reference in New Issue
Block a user