added smooth animation when a gauge value changes
This commit is contained in:
parent
f9a7e3ceda
commit
bd851a06f7
@ -51,7 +51,7 @@ export class GaugeCircular extends Gauge {
|
|||||||
bg.classList.add('gauge-bg');
|
bg.classList.add('gauge-bg');
|
||||||
svgElement.append(bg);
|
svgElement.append(bg);
|
||||||
|
|
||||||
let barHeight = 12;
|
let barHeight = 10;
|
||||||
const barGap = barHeight * 0.2;
|
const barGap = barHeight * 0.2;
|
||||||
let numBars = Math.round(arcLength / (barHeight + barGap));
|
let numBars = Math.round(arcLength / (barHeight + barGap));
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ export class GaugeLinear extends Gauge {
|
|||||||
bg.classList.add('gauge-bg');
|
bg.classList.add('gauge-bg');
|
||||||
svgElement.append(bg);
|
svgElement.append(bg);
|
||||||
|
|
||||||
let barHeight = 15;
|
let barHeight = 10;
|
||||||
const barGap = barHeight * 0.2;
|
const barGap = barHeight * 0.2;
|
||||||
let numBars = Math.round((h - paddingTop) / (barHeight + barGap));
|
let numBars = Math.round((h - paddingTop) / (barHeight + barGap));
|
||||||
|
|
||||||
|
@ -14,6 +14,17 @@ export class Gauge extends Widget {
|
|||||||
private integralValueElement: HTMLElement;
|
private integralValueElement: HTMLElement;
|
||||||
private decimalValueElement: HTMLElement;
|
private decimalValueElement: HTMLElement;
|
||||||
|
|
||||||
|
private displayedValue = 0.0;
|
||||||
|
private targetValue = 0.0;
|
||||||
|
private valueChangeRate = 0.0;
|
||||||
|
private litBars = 0;
|
||||||
|
|
||||||
|
private animating = false;
|
||||||
|
private shuttingDown = false;
|
||||||
|
|
||||||
|
private lastGaugeUpdate = 0.0;
|
||||||
|
private lastAnimationTick = 0.0;
|
||||||
|
|
||||||
constructor(vnode: any) {
|
constructor(vnode: any) {
|
||||||
super(vnode);
|
super(vnode);
|
||||||
|
|
||||||
@ -25,6 +36,11 @@ export class Gauge extends Widget {
|
|||||||
this.gaugeValue.onChange(() => this.updateGauge());
|
this.gaugeValue.onChange(() => this.updateGauge());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onbeforeremove(vnode: m.Vnode<{}, {}>) {
|
||||||
|
this.shuttingDown = true;
|
||||||
|
super.onbeforeremove(vnode);
|
||||||
|
}
|
||||||
|
|
||||||
view(vnode: m.Vnode<{}, {}>): m.Children {
|
view(vnode: m.Vnode<{}, {}>): m.Children {
|
||||||
return <div class="widget gauge" style={'flex: ' + this.widgetWidth}>
|
return <div class="widget gauge" style={'flex: ' + this.widgetWidth}>
|
||||||
<p><span class="integral-value"></span><span class="decimal-value"></span><span class="unit">{this.unit}</span></p>
|
<p><span class="integral-value"></span><span class="decimal-value"></span><span class="unit">{this.unit}</span></p>
|
||||||
@ -34,6 +50,8 @@ export class Gauge extends Widget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateGauge() {
|
updateGauge() {
|
||||||
|
let now = Date.now() / 1000.0;
|
||||||
|
|
||||||
let value = Math.max(0.0, Math.min(this.gaugeMaxValue, this.gaugeValue.get()));
|
let value = Math.max(0.0, Math.min(this.gaugeMaxValue, this.gaugeValue.get()));
|
||||||
|
|
||||||
let integralValue = Math.floor(value);
|
let integralValue = Math.floor(value);
|
||||||
@ -44,10 +62,66 @@ export class Gauge extends Widget {
|
|||||||
|
|
||||||
let ratio = value / this.gaugeMaxValue;
|
let ratio = value / this.gaugeMaxValue;
|
||||||
let numBars = this.bars.length;
|
let numBars = this.bars.length;
|
||||||
let litBars = Math.round(ratio * numBars);
|
let threshold = 0.33 / numBars;
|
||||||
|
|
||||||
|
if(ratio > this.targetValue + threshold || ratio < this.targetValue - threshold) {
|
||||||
|
let animationTime = this.lastGaugeUpdate == 0.0 ? 0.0001 : Math.max(0.0001, Math.min(0.75, now - this.lastGaugeUpdate));
|
||||||
|
|
||||||
|
this.valueChangeRate = (ratio - this.displayedValue) / animationTime;
|
||||||
|
this.targetValue = ratio;
|
||||||
|
|
||||||
|
this.enableAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.lastGaugeUpdate = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
private enableAnimation() {
|
||||||
|
if(this.animating) return;
|
||||||
|
this.animating = true;
|
||||||
|
this.lastAnimationTick = Date.now() / 1000.0 - 0.016;
|
||||||
|
requestAnimationFrame(() => this.animate());
|
||||||
|
}
|
||||||
|
|
||||||
|
private animate() {
|
||||||
|
if(this.shuttingDown) return;
|
||||||
|
|
||||||
|
if(this.valueChangeRate == 0.0) {
|
||||||
|
this.animating = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
requestAnimationFrame(() => this.animate());
|
||||||
|
|
||||||
|
let now = Date.now() / 1000.0;
|
||||||
|
if(now > this.lastAnimationTick + 0.75) {
|
||||||
|
this.displayedValue = this.targetValue;
|
||||||
|
this.valueChangeRate = 0.0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let dt = now - this.lastAnimationTick;
|
||||||
|
if(dt < 0.04) return; // limit framerate to save battery
|
||||||
|
|
||||||
|
this.displayedValue += this.valueChangeRate * dt;
|
||||||
|
if((this.displayedValue > this.targetValue) == (this.valueChangeRate > 0.0)) {
|
||||||
|
this.displayedValue = this.targetValue;
|
||||||
|
this.valueChangeRate = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.lastAnimationTick = now;
|
||||||
|
|
||||||
|
let numBars = this.bars.length;
|
||||||
|
let litBars = Math.round(this.displayedValue * numBars);
|
||||||
|
if(litBars == this.litBars)
|
||||||
|
return;
|
||||||
|
this.litBars = litBars;
|
||||||
|
|
||||||
for(let barIdx = 0; barIdx < numBars; ++barIdx) {
|
for(let barIdx = 0; barIdx < numBars; ++barIdx) {
|
||||||
let bar = this.bars[barIdx];
|
let bar = this.bars[barIdx];
|
||||||
bar.classList.toggle('lit', barIdx < litBars);
|
let isLit = barIdx < litBars;
|
||||||
|
if(bar.classList.contains('lit') != isLit)
|
||||||
|
bar.classList.toggle('lit', isLit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,14 +37,8 @@ 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 = {
|
|
||||||
v: Math.random() * 6000 + 36000,
|
|
||||||
c: Math.random() * 30000,
|
|
||||||
s: Math.random() * 14000,
|
|
||||||
t: Math.random() * 400 - 100,
|
|
||||||
alt: Math.random() * 4500000 - 200000
|
|
||||||
};*/
|
|
||||||
let t = new Date().getTime() / 1000.0;
|
let t = new Date().getTime() / 1000.0;
|
||||||
apiStatus = {
|
apiStatus = {
|
||||||
v: (Math.cos(t*0.4)+1.0)*0.5 * 6000 + 36000,
|
v: (Math.cos(t*0.4)+1.0)*0.5 * 6000 + 36000,
|
||||||
|
Loading…
Reference in New Issue
Block a user