Reimplement mempool animation smoothing within viz component
This commit is contained in:
parent
a8868b5f0f
commit
44116424b0
@ -81,6 +81,20 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
|
|||||||
tooltipPosition: Position;
|
tooltipPosition: Position;
|
||||||
|
|
||||||
readyNextFrame = false;
|
readyNextFrame = false;
|
||||||
|
lastUpdate: number = 0;
|
||||||
|
pendingUpdate: {
|
||||||
|
count: number,
|
||||||
|
add: { [txid: string]: TransactionStripped },
|
||||||
|
remove: { [txid: string]: string },
|
||||||
|
change: { [txid: string]: { txid: string, rate: number | undefined, acc: boolean | undefined } },
|
||||||
|
direction?: string,
|
||||||
|
} = {
|
||||||
|
count: 0,
|
||||||
|
add: {},
|
||||||
|
remove: {},
|
||||||
|
change: {},
|
||||||
|
direction: 'left',
|
||||||
|
};
|
||||||
|
|
||||||
searchText: string;
|
searchText: string;
|
||||||
searchSubscription: Subscription;
|
searchSubscription: Subscription;
|
||||||
@ -176,6 +190,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
|
|||||||
destroy(): void {
|
destroy(): void {
|
||||||
if (this.scene) {
|
if (this.scene) {
|
||||||
this.scene.destroy();
|
this.scene.destroy();
|
||||||
|
this.clearUpdateQueue();
|
||||||
this.start();
|
this.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -188,6 +203,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
|
|||||||
}
|
}
|
||||||
this.filtersAvailable = filtersAvailable;
|
this.filtersAvailable = filtersAvailable;
|
||||||
if (this.scene) {
|
if (this.scene) {
|
||||||
|
this.clearUpdateQueue();
|
||||||
this.scene.setup(transactions);
|
this.scene.setup(transactions);
|
||||||
this.readyNextFrame = true;
|
this.readyNextFrame = true;
|
||||||
this.start();
|
this.start();
|
||||||
@ -197,6 +213,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
|
|||||||
|
|
||||||
enter(transactions: TransactionStripped[], direction: string): void {
|
enter(transactions: TransactionStripped[], direction: string): void {
|
||||||
if (this.scene) {
|
if (this.scene) {
|
||||||
|
this.clearUpdateQueue();
|
||||||
this.scene.enter(transactions, direction);
|
this.scene.enter(transactions, direction);
|
||||||
this.start();
|
this.start();
|
||||||
this.updateSearchHighlight();
|
this.updateSearchHighlight();
|
||||||
@ -205,6 +222,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
|
|||||||
|
|
||||||
exit(direction: string): void {
|
exit(direction: string): void {
|
||||||
if (this.scene) {
|
if (this.scene) {
|
||||||
|
this.clearUpdateQueue();
|
||||||
this.scene.exit(direction);
|
this.scene.exit(direction);
|
||||||
this.start();
|
this.start();
|
||||||
this.updateSearchHighlight();
|
this.updateSearchHighlight();
|
||||||
@ -213,13 +231,61 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
|
|||||||
|
|
||||||
replace(transactions: TransactionStripped[], direction: string, sort: boolean = true, startTime?: number): void {
|
replace(transactions: TransactionStripped[], direction: string, sort: boolean = true, startTime?: number): void {
|
||||||
if (this.scene) {
|
if (this.scene) {
|
||||||
|
this.clearUpdateQueue();
|
||||||
this.scene.replace(transactions || [], direction, sort, startTime);
|
this.scene.replace(transactions || [], direction, sort, startTime);
|
||||||
this.start();
|
this.start();
|
||||||
this.updateSearchHighlight();
|
this.updateSearchHighlight();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// collates non-urgent updates into a set of consistent pending changes
|
||||||
|
queueUpdate(add: TransactionStripped[], remove: string[], change: { txid: string, rate: number | undefined, acc: boolean | undefined }[], direction: string = 'left'): void {
|
||||||
|
for (const tx of add) {
|
||||||
|
this.pendingUpdate.add[tx.txid] = tx;
|
||||||
|
delete this.pendingUpdate.remove[tx.txid];
|
||||||
|
delete this.pendingUpdate.change[tx.txid];
|
||||||
|
}
|
||||||
|
for (const txid of remove) {
|
||||||
|
delete this.pendingUpdate.add[txid];
|
||||||
|
this.pendingUpdate.remove[txid] = txid;
|
||||||
|
delete this.pendingUpdate.change[txid];
|
||||||
|
}
|
||||||
|
for (const tx of change) {
|
||||||
|
if (this.pendingUpdate.add[tx.txid]) {
|
||||||
|
this.pendingUpdate.add[tx.txid].rate = tx.rate;
|
||||||
|
this.pendingUpdate.add[tx.txid].acc = tx.acc;
|
||||||
|
} else {
|
||||||
|
this.pendingUpdate.change[tx.txid] = tx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.pendingUpdate.direction = direction;
|
||||||
|
this.pendingUpdate.count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
applyQueuedUpdates(): void {
|
||||||
|
if (this.pendingUpdate.count && performance.now() > (this.lastUpdate + this.animationDuration)) {
|
||||||
|
this.update([], [], [], this.pendingUpdate?.direction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clearUpdateQueue(): void {
|
||||||
|
this.pendingUpdate = {
|
||||||
|
count: 0,
|
||||||
|
add: {},
|
||||||
|
remove: {},
|
||||||
|
change: {},
|
||||||
|
};
|
||||||
|
this.lastUpdate = performance.now();
|
||||||
|
}
|
||||||
|
|
||||||
update(add: TransactionStripped[], remove: string[], change: { txid: string, rate: number | undefined, acc: boolean | undefined }[], direction: string = 'left', resetLayout: boolean = false): void {
|
update(add: TransactionStripped[], remove: string[], change: { txid: string, rate: number | undefined, acc: boolean | undefined }[], direction: string = 'left', resetLayout: boolean = false): void {
|
||||||
|
// merge any pending changes into this update
|
||||||
|
this.queueUpdate(add, remove, change);
|
||||||
|
this.applyUpdate(Object.values(this.pendingUpdate.add), Object.values(this.pendingUpdate.remove), Object.values(this.pendingUpdate.change), direction, resetLayout);
|
||||||
|
this.clearUpdateQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
applyUpdate(add: TransactionStripped[], remove: string[], change: { txid: string, rate: number | undefined, acc: boolean | undefined }[], direction: string = 'left', resetLayout: boolean = false): void {
|
||||||
if (this.scene) {
|
if (this.scene) {
|
||||||
add = add.filter(tx => !this.scene.txs[tx.txid]);
|
add = add.filter(tx => !this.scene.txs[tx.txid]);
|
||||||
remove = remove.filter(txid => this.scene.txs[txid]);
|
remove = remove.filter(txid => this.scene.txs[txid]);
|
||||||
@ -230,6 +296,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
|
|||||||
}
|
}
|
||||||
this.scene.update(add, remove, change, direction, resetLayout);
|
this.scene.update(add, remove, change, direction, resetLayout);
|
||||||
this.start();
|
this.start();
|
||||||
|
this.lastUpdate = performance.now();
|
||||||
this.updateSearchHighlight();
|
this.updateSearchHighlight();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -370,6 +437,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
|
|||||||
if (!now) {
|
if (!now) {
|
||||||
now = performance.now();
|
now = performance.now();
|
||||||
}
|
}
|
||||||
|
this.applyQueuedUpdates();
|
||||||
// skip re-render if there's no change to the scene
|
// skip re-render if there's no change to the scene
|
||||||
if (this.scene && this.gl) {
|
if (this.scene && this.gl) {
|
||||||
/* SET UP SHADER UNIFORMS */
|
/* SET UP SHADER UNIFORMS */
|
||||||
|
@ -13,7 +13,7 @@ export default class BlockScene {
|
|||||||
theme: ThemeService;
|
theme: ThemeService;
|
||||||
orientation: string;
|
orientation: string;
|
||||||
flip: boolean;
|
flip: boolean;
|
||||||
animationDuration: number = 900;
|
animationDuration: number = 1000;
|
||||||
configAnimationOffset: number | null;
|
configAnimationOffset: number | null;
|
||||||
animationOffset: number;
|
animationOffset: number;
|
||||||
highlightingEnabled: boolean;
|
highlightingEnabled: boolean;
|
||||||
@ -179,7 +179,7 @@ export default class BlockScene {
|
|||||||
removed.forEach(tx => {
|
removed.forEach(tx => {
|
||||||
tx.destroy();
|
tx.destroy();
|
||||||
});
|
});
|
||||||
}, 1000);
|
}, (startTime - performance.now()) + this.animationDuration + 1000);
|
||||||
|
|
||||||
if (resetLayout) {
|
if (resetLayout) {
|
||||||
add.forEach(tx => {
|
add.forEach(tx => {
|
||||||
@ -239,7 +239,7 @@ export default class BlockScene {
|
|||||||
{ width: number, height: number, resolution: number, blockLimit: number, animationDuration: number, animationOffset: number,
|
{ width: number, height: number, resolution: number, blockLimit: number, animationDuration: number, animationOffset: number,
|
||||||
orientation: string, flip: boolean, vertexArray: FastVertexArray, theme: ThemeService, highlighting: boolean, colorFunction: ((tx: TxView) => Color) | null }
|
orientation: string, flip: boolean, vertexArray: FastVertexArray, theme: ThemeService, highlighting: boolean, colorFunction: ((tx: TxView) => Color) | null }
|
||||||
): void {
|
): void {
|
||||||
this.animationDuration = animationDuration || 1000;
|
this.animationDuration = animationDuration || this.animationDuration || 1000;
|
||||||
this.configAnimationOffset = animationOffset;
|
this.configAnimationOffset = animationOffset;
|
||||||
this.animationOffset = this.configAnimationOffset == null ? (this.width * 1.4) : this.configAnimationOffset;
|
this.animationOffset = this.configAnimationOffset == null ? (this.width * 1.4) : this.configAnimationOffset;
|
||||||
this.orientation = orientation;
|
this.orientation = orientation;
|
||||||
|
@ -141,7 +141,11 @@ export class MempoolBlockOverviewComponent implements OnInit, OnDestroy, OnChang
|
|||||||
const direction = (this.blockIndex == null || this.index < this.blockIndex) ? this.poolDirection : this.chainDirection;
|
const direction = (this.blockIndex == null || this.index < this.blockIndex) ? this.poolDirection : this.chainDirection;
|
||||||
this.blockGraph.replace(delta.added, direction);
|
this.blockGraph.replace(delta.added, direction);
|
||||||
} else {
|
} else {
|
||||||
this.blockGraph.update(delta.added, delta.removed, delta.changed || [], blockMined ? this.chainDirection : this.poolDirection, blockMined);
|
if (blockMined) {
|
||||||
|
this.blockGraph.update(delta.added, delta.removed, delta.changed || [], blockMined ? this.chainDirection : this.poolDirection, blockMined);
|
||||||
|
} else {
|
||||||
|
this.blockGraph.queueUpdate(delta.added, delta.removed, delta.changed || [], this.poolDirection);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.lastBlockHeight = this.stateService.latestBlockHeight;
|
this.lastBlockHeight = this.stateService.latestBlockHeight;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user