better styling of gauges (battery shape and inclined shape)
This commit is contained in:
parent
44a69a8d0b
commit
f9a7e3ceda
27
WebApp/src/components/widgets/gauge-battery.tsx
Normal file
27
WebApp/src/components/widgets/gauge-battery.tsx
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import m from 'mithril';
|
||||||
|
import { GaugeLinear } from 'components/widgets/gauge-linear';
|
||||||
|
|
||||||
|
export class GaugeBattery extends GaugeLinear {
|
||||||
|
constructor(vnode: any) {
|
||||||
|
super(vnode);
|
||||||
|
this.svgPaddingTop = 0.06;
|
||||||
|
}
|
||||||
|
|
||||||
|
createSvg(svgElement: SVGElement) {
|
||||||
|
super.createSvg(svgElement);
|
||||||
|
|
||||||
|
let w = Math.round(svgElement.clientWidth);
|
||||||
|
let h = Math.round(svgElement.clientHeight);
|
||||||
|
let paddingTop = Math.round(svgElement.clientHeight * this.svgPaddingTop);
|
||||||
|
|
||||||
|
const batteryTopWidth = 0.5;
|
||||||
|
|
||||||
|
let batteryTop = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
|
||||||
|
batteryTop.setAttribute('width', (w * batteryTopWidth).toFixed(1));
|
||||||
|
batteryTop.setAttribute('height', (paddingTop).toString());
|
||||||
|
batteryTop.setAttribute('x', (w * (1.0 - batteryTopWidth)*0.5).toFixed(1));
|
||||||
|
batteryTop.setAttribute('y', '0');
|
||||||
|
batteryTop.classList.add('gauge-bg');
|
||||||
|
svgElement.append(batteryTop);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
div.gauge svg.gauge-circular path.gauge-bg-outline {
|
||||||
|
stroke: rgb(0,0,0);
|
||||||
|
fill: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.gauge svg.gauge-circular path.gauge-bg {
|
||||||
|
stroke: rgb(255,255,255);
|
||||||
|
fill: none;
|
||||||
|
}
|
@ -13,6 +13,8 @@ export class GaugeCircular extends Gauge {
|
|||||||
let w = Math.round(svgElement.clientWidth);
|
let w = Math.round(svgElement.clientWidth);
|
||||||
let h = Math.round(svgElement.clientHeight);
|
let h = Math.round(svgElement.clientHeight);
|
||||||
|
|
||||||
|
svgElement.classList.add('gauge-circular');
|
||||||
|
|
||||||
svgElement.setAttribute('viewBox', "0 0 "+w+" "+h);
|
svgElement.setAttribute('viewBox', "0 0 "+w+" "+h);
|
||||||
|
|
||||||
let svgRound = (v: number) => Math.round(v * 100.0) / 100.0;
|
let svgRound = (v: number) => Math.round(v * 100.0) / 100.0;
|
||||||
|
@ -5,32 +5,47 @@ import { Pipe } from 'utilities/pipe';
|
|||||||
require('./gauge-linear.css');
|
require('./gauge-linear.css');
|
||||||
|
|
||||||
export class GaugeLinear extends Gauge {
|
export class GaugeLinear extends Gauge {
|
||||||
|
protected svgPaddingTop = 0.0;
|
||||||
|
private bottomWidth: number;
|
||||||
|
private topWidth: number;
|
||||||
|
|
||||||
constructor(vnode: any) {
|
constructor(vnode: any) {
|
||||||
super(vnode);
|
super(vnode);
|
||||||
|
|
||||||
|
this.bottomWidth = vnode.attrs.bottomWidth || 1.0;
|
||||||
|
this.topWidth = vnode.attrs.topWidth || 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
createSvg(svgElement: SVGElement) {
|
createSvg(svgElement: SVGElement) {
|
||||||
let w = Math.round(svgElement.clientWidth);
|
let w = Math.round(svgElement.clientWidth);
|
||||||
let h = Math.round(svgElement.clientHeight);
|
let h = Math.round(svgElement.clientHeight);
|
||||||
|
let paddingTop = Math.round(svgElement.clientHeight * this.svgPaddingTop);
|
||||||
|
|
||||||
svgElement.setAttribute('viewBox', "0 0 "+w+" "+h);
|
svgElement.setAttribute('viewBox', "0 0 "+w+" "+h);
|
||||||
|
|
||||||
|
let svgRound = (v: number) => Math.round(v * 100.0) / 100.0;
|
||||||
|
|
||||||
let bg = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
|
let bg = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
||||||
bg.setAttribute('width', w.toString());
|
//bg.setAttribute('width', w.toString());
|
||||||
bg.setAttribute('height', h.toString());
|
//bg.setAttribute('height', (h - paddingTop).toString());
|
||||||
|
//bg.setAttribute('y', paddingTop.toString());
|
||||||
|
bg.setAttribute('d', 'M0,'+paddingTop+' L'+svgRound(w*this.topWidth)+','+paddingTop+' L'+svgRound(w*this.bottomWidth)+','+h+' L0,'+h+' Z');
|
||||||
bg.classList.add('gauge-bg');
|
bg.classList.add('gauge-bg');
|
||||||
svgElement.append(bg);
|
svgElement.append(bg);
|
||||||
|
|
||||||
let barHeight = 15;
|
let barHeight = 15;
|
||||||
const barGap = barHeight * 0.2;
|
const barGap = barHeight * 0.2;
|
||||||
let numBars = Math.round(h / (barHeight + barGap));
|
let numBars = Math.round((h - paddingTop) / (barHeight + barGap));
|
||||||
|
|
||||||
let bh = (h - (numBars+1)*barGap) / numBars;
|
let bh = ((h - paddingTop) - (numBars+1)*barGap) / numBars;
|
||||||
barHeight = Math.round(bh);
|
barHeight = Math.round(bh);
|
||||||
|
|
||||||
for(let barIdx = 0; barIdx < numBars; ++barIdx) {
|
for(let barIdx = 0; barIdx < numBars; ++barIdx) {
|
||||||
let bar = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
|
let bar = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
|
||||||
bar.setAttribute('width', (w - barGap * 2).toString());
|
let barW = w * ((barGap + barIdx * (bh+barGap))/(h - paddingTop) * (this.topWidth - this.bottomWidth) + this.bottomWidth);
|
||||||
|
let barW1 = w * ((barGap + barIdx * (bh+barGap) + bh)/(h - paddingTop) * (this.topWidth - this.bottomWidth) + this.bottomWidth);
|
||||||
|
barW = Math.min(barW, barW1);
|
||||||
|
bar.setAttribute('width', (barW - barGap * 2).toString());
|
||||||
bar.setAttribute('height', barHeight.toString());
|
bar.setAttribute('height', barHeight.toString());
|
||||||
bar.classList.add('gauge-bar');
|
bar.classList.add('gauge-bar');
|
||||||
bar.classList.toggle('lit', false);
|
bar.classList.toggle('lit', false);
|
||||||
|
@ -22,22 +22,12 @@ div.gauge span.unit {
|
|||||||
font-size: 1.6rem;
|
font-size: 1.6rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
rect.gauge-bg {
|
.gauge-bg {
|
||||||
fill: rgb(255,255,255);
|
fill: rgb(255,255,255);
|
||||||
stroke-width: 2;
|
stroke-width: 2;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.gauge .gauge-bar {
|
div.gauge .gauge-bar {
|
||||||
fill: rgb(230,230,230);
|
fill: rgb(230,230,230);
|
||||||
stroke-width: 1;
|
stroke-width: 1;
|
||||||
|
@ -37,14 +37,22 @@ export class MonitorApi {
|
|||||||
let apiStatus: ApiStatus;
|
let apiStatus: ApiStatus;
|
||||||
|
|
||||||
if(this.mockServer) {
|
if(this.mockServer) {
|
||||||
await new Promise(resolve => setTimeout(resolve, 200));
|
//await new Promise(resolve => setTimeout(resolve, 200));
|
||||||
apiStatus = {
|
/*apiStatus = {
|
||||||
v: Math.random() * 6000 + 36000,
|
v: Math.random() * 6000 + 36000,
|
||||||
c: Math.random() * 30000,
|
c: Math.random() * 30000,
|
||||||
s: Math.random() * 14000,
|
s: Math.random() * 14000,
|
||||||
t: Math.random() * 400 - 100,
|
t: Math.random() * 400 - 100,
|
||||||
alt: Math.random() * 4500000 - 200000
|
alt: Math.random() * 4500000 - 200000
|
||||||
}
|
};*/
|
||||||
|
let t = new Date().getTime() / 1000.0;
|
||||||
|
apiStatus = {
|
||||||
|
v: (Math.cos(t*0.4)+1.0)*0.5 * 6000 + 36000,
|
||||||
|
c: (Math.cos(t*0.7)+1.0)*0.5 * 30000,
|
||||||
|
s: (Math.cos(t*0.3)+1.0)*0.5 * 14000,
|
||||||
|
t: Math.random() * 400 - 100,
|
||||||
|
alt: Math.random() * 4500000 - 200000
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
apiStatus = await new Promise<ApiStatus>((resolve, error) => {
|
apiStatus = await new Promise<ApiStatus>((resolve, error) => {
|
||||||
let request = new XMLHttpRequest();
|
let request = new XMLHttpRequest();
|
||||||
|
@ -6,6 +6,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';
|
import { GaugeCircular } from 'components/widgets/gauge-circular';
|
||||||
|
import { GaugeBattery } from 'components/widgets/gauge-battery';
|
||||||
|
|
||||||
require('./dashboard-page.css');
|
require('./dashboard-page.css');
|
||||||
|
|
||||||
@ -42,7 +43,7 @@ export class DashboardPage extends Page {
|
|||||||
this.speed.set(this.status.speed * 3.6); // convert m/s to km/h
|
this.speed.set(this.status.speed * 3.6); // convert m/s to km/h
|
||||||
|
|
||||||
if(this.autoRefresh)
|
if(this.autoRefresh)
|
||||||
setTimeout(() => { if(this.autoRefresh) this.refresh(); }, 500);
|
setTimeout(() => { if(this.autoRefresh) this.refresh(); }, 150);
|
||||||
}
|
}
|
||||||
|
|
||||||
view() {
|
view() {
|
||||||
@ -52,9 +53,9 @@ export class DashboardPage extends Page {
|
|||||||
<Clock/>
|
<Clock/>
|
||||||
</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} bottomWidth={0.4} unit="W" />
|
||||||
<GaugeCircular 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="%" />
|
<GaugeBattery widgetWidth={0.2} gaugeValue={this.battery} gaugeMaxValue={100.0} unit="%" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
: <p>Chargement...</p>;
|
: <p>Chargement...</p>;
|
||||||
|
Loading…
Reference in New Issue
Block a user