added chronometer
This commit is contained in:
parent
55bdad727b
commit
c7da034218
3
WebApp/src/components/widgets/chronometer.css
Normal file
3
WebApp/src/components/widgets/chronometer.css
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
div.widget.chronometer span.integral-value {
|
||||||
|
font-size: 2.0rem;
|
||||||
|
}
|
54
WebApp/src/components/widgets/chronometer.tsx
Normal file
54
WebApp/src/components/widgets/chronometer.tsx
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import { NumericValue } from 'components/widgets/numeric-value';
|
||||||
|
|
||||||
|
require('./chronometer.css');
|
||||||
|
|
||||||
|
export class Chronometer extends NumericValue {
|
||||||
|
private realTimeValue = 0;
|
||||||
|
private realTimeReference = 0;
|
||||||
|
|
||||||
|
private animating = false;
|
||||||
|
private shuttingDown = false;
|
||||||
|
|
||||||
|
protected mainClassName() { return 'numeric-value chronometer'; }
|
||||||
|
|
||||||
|
protected onValueChange(value: number) {
|
||||||
|
let now = Date.now() / 1000;
|
||||||
|
|
||||||
|
let realTimeValue = this.realTimeValue + (now - this.realTimeReference);
|
||||||
|
|
||||||
|
if(Math.abs(value - realTimeValue) < 2.0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.realTimeValue = value;
|
||||||
|
this.realTimeReference = now;
|
||||||
|
realTimeValue = value;
|
||||||
|
this.startAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
private startAnimation() {
|
||||||
|
if(this.animating)
|
||||||
|
return;
|
||||||
|
this.animating = true;
|
||||||
|
this.animate();
|
||||||
|
}
|
||||||
|
|
||||||
|
onbeforeremove(vnode: any) {
|
||||||
|
this.shuttingDown = true;
|
||||||
|
super.onbeforeremove(vnode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private animate() {
|
||||||
|
if(this.shuttingDown) return;
|
||||||
|
|
||||||
|
let now = Date.now() / 1000;
|
||||||
|
let realTimeValue = this.realTimeValue + (now - this.realTimeReference);
|
||||||
|
|
||||||
|
let hours = Math.floor(realTimeValue / 3600);
|
||||||
|
let minutes = Math.floor((realTimeValue - hours * 3600)/60);
|
||||||
|
let seconds = Math.floor(realTimeValue - hours * 3600 - minutes * 60);
|
||||||
|
|
||||||
|
this.integralValueElement.innerText = (hours < 10 ? '0' : '') + hours + ':' + (minutes < 10 ? '0' : '') + minutes + ':' + (seconds < 10 ? '0' : '') + seconds;
|
||||||
|
|
||||||
|
setTimeout(() => this.animate(), (Math.ceil(realTimeValue) + 0.05 - realTimeValue) * 1000);
|
||||||
|
}
|
||||||
|
}
|
@ -36,6 +36,8 @@ export class Gauge extends NumericValue {
|
|||||||
protected onValueChange(value: number) {
|
protected onValueChange(value: number) {
|
||||||
let now = Date.now() / 1000.0;
|
let now = Date.now() / 1000.0;
|
||||||
|
|
||||||
|
super.onValueChange(value);
|
||||||
|
|
||||||
let ratio = value / (this.maxValue || 1.0);
|
let ratio = value / (this.maxValue || 1.0);
|
||||||
let numBars = this.bars.length;
|
let numBars = this.bars.length;
|
||||||
let threshold = 0.33 / numBars;
|
let threshold = 0.33 / numBars;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
div.widget span.integral-value {
|
div.widget span.integral-value {
|
||||||
font-size: 2.3rem;
|
font-size: 2.2rem;
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,8 +13,8 @@ export class NumericValue extends Widget {
|
|||||||
|
|
||||||
protected icon?: string;
|
protected icon?: string;
|
||||||
|
|
||||||
private integralValueElement: HTMLElement;
|
protected integralValueElement: HTMLElement;
|
||||||
private decimalValueElement: HTMLElement;
|
protected decimalValueElement: HTMLElement;
|
||||||
|
|
||||||
constructor(vnode: any) {
|
constructor(vnode: any) {
|
||||||
super(vnode);
|
super(vnode);
|
||||||
@ -27,7 +27,7 @@ export class NumericValue extends Widget {
|
|||||||
|
|
||||||
this.icon = vnode.attrs.icon || null;
|
this.icon = vnode.attrs.icon || null;
|
||||||
|
|
||||||
this.value.onChange(() => this.onValueChange_());
|
this.value.onChange(() => this.onValueChange(this.getClampedValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
view(vnode: m.Vnode<{}, {}>): m.Children {
|
view(vnode: m.Vnode<{}, {}>): m.Children {
|
||||||
@ -48,27 +48,25 @@ export class NumericValue extends Widget {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected onValueChange(newValue: number) {
|
private getClampedValue() {
|
||||||
}
|
|
||||||
|
|
||||||
private onValueChange_() {
|
|
||||||
let value = this.value.get();
|
let value = this.value.get();
|
||||||
if(this.minValue !== null) value = Math.max(value, this.minValue);
|
if(this.minValue !== null) value = Math.max(value, this.minValue);
|
||||||
if(this.maxValue !== null) value = Math.min(value, this.maxValue);
|
if(this.maxValue !== null) value = Math.min(value, this.maxValue);
|
||||||
|
return value;
|
||||||
let valueStr = value.toFixed(this.decimals);
|
}
|
||||||
|
|
||||||
|
protected onValueChange(newValue: number) {
|
||||||
|
let valueStr = newValue.toFixed(this.decimals);
|
||||||
let parts = valueStr.split('.');
|
let parts = valueStr.split('.');
|
||||||
|
|
||||||
this.integralValueElement.innerText = parts[0];
|
this.integralValueElement.innerText = parts[0];
|
||||||
this.decimalValueElement.innerText = this.decimals > 0 ? '.' + parts[1] : '';
|
this.decimalValueElement.innerText = this.decimals > 0 ? '.' + parts[1] : '';
|
||||||
|
|
||||||
this.onValueChange(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
oncreate(vnode: any) {
|
oncreate(vnode: any) {
|
||||||
this.integralValueElement = vnode.dom.querySelector('span.integral-value');
|
this.integralValueElement = vnode.dom.querySelector('span.integral-value');
|
||||||
this.decimalValueElement = vnode.dom.querySelector('span.decimal-value');
|
this.decimalValueElement = vnode.dom.querySelector('span.decimal-value');
|
||||||
|
|
||||||
this.onValueChange_();
|
this.onValueChange(this.getClampedValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import { Pipe } from 'utilities/pipe';
|
|||||||
|
|
||||||
import { Clock } from 'components/widgets/clock';
|
import { Clock } from 'components/widgets/clock';
|
||||||
import { NumericValue } from 'components/widgets/numeric-value';
|
import { NumericValue } from 'components/widgets/numeric-value';
|
||||||
|
import { Chronometer } from 'components/widgets/chronometer';
|
||||||
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';
|
import { GaugeBattery } from 'components/widgets/gauge-battery';
|
||||||
@ -28,6 +29,7 @@ export class DashboardPage extends Page {
|
|||||||
private battery = new Pipe(0.0);
|
private battery = new Pipe(0.0);
|
||||||
private speed = new Pipe(0.0);
|
private speed = new Pipe(0.0);
|
||||||
|
|
||||||
|
private tripTotalTime = new Pipe(0.0);
|
||||||
private tripDistance = new Pipe(0.0);
|
private tripDistance = new Pipe(0.0);
|
||||||
private tripAverageSpeed = new Pipe(0.0);
|
private tripAverageSpeed = new Pipe(0.0);
|
||||||
private tripEnergy = new Pipe(0.0);
|
private tripEnergy = new Pipe(0.0);
|
||||||
@ -62,6 +64,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
|
||||||
|
|
||||||
|
this.tripTotalTime.set(this.status.tripTotalTime);
|
||||||
this.tripDistance.set(this.status.tripDistance/1000);
|
this.tripDistance.set(this.status.tripDistance/1000);
|
||||||
this.tripAverageSpeed.set(this.status.tripDistance/1000 / (Math.max(1.0, this.status.tripMovingTime)/3600));
|
this.tripAverageSpeed.set(this.status.tripDistance/1000 / (Math.max(1.0, this.status.tripMovingTime)/3600));
|
||||||
this.tripEnergy.set(this.status.tripMotorEnergy);
|
this.tripEnergy.set(this.status.tripMotorEnergy);
|
||||||
@ -72,7 +75,7 @@ export class DashboardPage extends Page {
|
|||||||
this.altitude.set(this.status.altitude);
|
this.altitude.set(this.status.altitude);
|
||||||
|
|
||||||
if(this.autoRefresh)
|
if(this.autoRefresh)
|
||||||
setTimeout(() => { if(this.autoRefresh) this.refresh(); }, 150);
|
setTimeout(() => { if(this.autoRefresh) this.refresh(); }, 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
view() {
|
view() {
|
||||||
@ -90,6 +93,7 @@ export class DashboardPage extends Page {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="widgets-row">
|
<div class="widgets-row">
|
||||||
|
<Chronometer icon={TimeIcon} widgetWidth={0.5} value={this.tripTotalTime} />
|
||||||
<NumericValue icon={DistanceIcon} widgetWidth={0.5} value={this.tripDistance} decimals={1} unit="km" />
|
<NumericValue icon={DistanceIcon} widgetWidth={0.5} value={this.tripDistance} decimals={1} unit="km" />
|
||||||
</div>
|
</div>
|
||||||
<div class="widgets-row">
|
<div class="widgets-row">
|
||||||
|
Loading…
Reference in New Issue
Block a user