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');
|
||||
svgElement.append(bg);
|
||||
|
||||
let barHeight = 12;
|
||||
let barHeight = 10;
|
||||
const barGap = barHeight * 0.2;
|
||||
let numBars = Math.round(arcLength / (barHeight + barGap));
|
||||
|
||||
|
@ -33,7 +33,7 @@ export class GaugeLinear extends Gauge {
|
||||
bg.classList.add('gauge-bg');
|
||||
svgElement.append(bg);
|
||||
|
||||
let barHeight = 15;
|
||||
let barHeight = 10;
|
||||
const barGap = barHeight * 0.2;
|
||||
let numBars = Math.round((h - paddingTop) / (barHeight + barGap));
|
||||
|
||||
|
@ -14,6 +14,17 @@ export class Gauge extends Widget {
|
||||
private integralValueElement: 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) {
|
||||
super(vnode);
|
||||
|
||||
@ -25,6 +36,11 @@ export class Gauge extends Widget {
|
||||
this.gaugeValue.onChange(() => this.updateGauge());
|
||||
}
|
||||
|
||||
onbeforeremove(vnode: m.Vnode<{}, {}>) {
|
||||
this.shuttingDown = true;
|
||||
super.onbeforeremove(vnode);
|
||||
}
|
||||
|
||||
view(vnode: m.Vnode<{}, {}>): m.Children {
|
||||
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>
|
||||
@ -34,6 +50,8 @@ export class Gauge extends Widget {
|
||||
}
|
||||
|
||||
updateGauge() {
|
||||
let now = Date.now() / 1000.0;
|
||||
|
||||
let value = Math.max(0.0, Math.min(this.gaugeMaxValue, this.gaugeValue.get()));
|
||||
|
||||
let integralValue = Math.floor(value);
|
||||
@ -44,10 +62,66 @@ export class Gauge extends Widget {
|
||||
|
||||
let ratio = value / this.gaugeMaxValue;
|
||||
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) {
|
||||
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;
|
||||
|
||||
if(this.mockServer) {
|
||||
//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
|
||||
};*/
|
||||
await new Promise(resolve => setTimeout(resolve, 200));
|
||||
|
||||
let t = new Date().getTime() / 1000.0;
|
||||
apiStatus = {
|
||||
v: (Math.cos(t*0.4)+1.0)*0.5 * 6000 + 36000,
|
||||
|
Loading…
Reference in New Issue
Block a user