Optimize block visualization rendering
This commit is contained in:
parent
7f4c6352ba
commit
300f5375c8
@ -1,4 +1,4 @@
|
|||||||
import { Component, ElementRef, ViewChild, HostListener, Input, Output, EventEmitter, NgZone, AfterViewInit } from '@angular/core';
|
import { Component, ElementRef, ViewChild, HostListener, Input, Output, EventEmitter, NgZone, AfterViewInit, OnDestroy } from '@angular/core';
|
||||||
import { MempoolBlockDelta, TransactionStripped } from 'src/app/interfaces/websocket.interface';
|
import { MempoolBlockDelta, TransactionStripped } from 'src/app/interfaces/websocket.interface';
|
||||||
import { WebsocketService } from 'src/app/services/websocket.service';
|
import { WebsocketService } from 'src/app/services/websocket.service';
|
||||||
import { FastVertexArray } from './fast-vertex-array';
|
import { FastVertexArray } from './fast-vertex-array';
|
||||||
@ -11,7 +11,7 @@ import TxView from './tx-view';
|
|||||||
templateUrl: './block-overview-graph.component.html',
|
templateUrl: './block-overview-graph.component.html',
|
||||||
styleUrls: ['./block-overview-graph.component.scss'],
|
styleUrls: ['./block-overview-graph.component.scss'],
|
||||||
})
|
})
|
||||||
export class BlockOverviewGraphComponent implements AfterViewInit {
|
export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy {
|
||||||
@Input() isLoading: boolean;
|
@Input() isLoading: boolean;
|
||||||
@Input() resolution: number;
|
@Input() resolution: number;
|
||||||
@Input() blockLimit: number;
|
@Input() blockLimit: number;
|
||||||
@ -24,6 +24,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit {
|
|||||||
|
|
||||||
gl: WebGLRenderingContext;
|
gl: WebGLRenderingContext;
|
||||||
animationFrameRequest: number;
|
animationFrameRequest: number;
|
||||||
|
animationHeartBeat: number;
|
||||||
displayWidth: number;
|
displayWidth: number;
|
||||||
displayHeight: number;
|
displayHeight: number;
|
||||||
cssWidth: number;
|
cssWidth: number;
|
||||||
@ -50,34 +51,46 @@ export class BlockOverviewGraphComponent implements AfterViewInit {
|
|||||||
this.resizeCanvas();
|
this.resizeCanvas();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
if (this.animationFrameRequest) {
|
||||||
|
cancelAnimationFrame(this.animationFrameRequest);
|
||||||
|
clearTimeout(this.animationHeartBeat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
clear(direction): void {
|
clear(direction): void {
|
||||||
this.exit(direction);
|
this.exit(direction);
|
||||||
this.hoverTx = null;
|
this.hoverTx = null;
|
||||||
this.selectedTx = null;
|
this.selectedTx = null;
|
||||||
this.txPreviewEvent.emit(null);
|
this.txPreviewEvent.emit(null);
|
||||||
|
this.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
enter(transactions: TransactionStripped[], direction: string): void {
|
enter(transactions: TransactionStripped[], direction: string): void {
|
||||||
if (this.scene) {
|
if (this.scene) {
|
||||||
this.scene.enter(transactions, direction);
|
this.scene.enter(transactions, direction);
|
||||||
|
this.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exit(direction: string): void {
|
exit(direction: string): void {
|
||||||
if (this.scene) {
|
if (this.scene) {
|
||||||
this.scene.exit(direction);
|
this.scene.exit(direction);
|
||||||
|
this.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
replace(transactions: TransactionStripped[], direction: string, sort: boolean = true): void {
|
replace(transactions: TransactionStripped[], direction: string, sort: boolean = true): void {
|
||||||
if (this.scene) {
|
if (this.scene) {
|
||||||
this.scene.replace(transactions || [], direction, sort);
|
this.scene.replace(transactions || [], direction, sort);
|
||||||
|
this.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
update(add: TransactionStripped[], remove: string[], direction: string = 'left', resetLayout: boolean = false): void {
|
update(add: TransactionStripped[], remove: string[], direction: string = 'left', resetLayout: boolean = false): void {
|
||||||
if (this.scene) {
|
if (this.scene) {
|
||||||
this.scene.update(add, remove, direction, resetLayout);
|
this.scene.update(add, remove, direction, resetLayout);
|
||||||
|
this.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,6 +153,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit {
|
|||||||
}
|
}
|
||||||
if (this.scene) {
|
if (this.scene) {
|
||||||
this.scene.resize({ width: this.displayWidth, height: this.displayHeight });
|
this.scene.resize({ width: this.displayWidth, height: this.displayHeight });
|
||||||
|
this.start();
|
||||||
} else {
|
} else {
|
||||||
this.scene = new BlockScene({ width: this.displayWidth, height: this.displayHeight, resolution: this.resolution,
|
this.scene = new BlockScene({ width: this.displayWidth, height: this.displayHeight, resolution: this.resolution,
|
||||||
blockLimit: this.blockLimit, orientation: this.orientation, flip: this.flip, vertexArray: this.vertexArray });
|
blockLimit: this.blockLimit, orientation: this.orientation, flip: this.flip, vertexArray: this.vertexArray });
|
||||||
@ -182,44 +196,64 @@ export class BlockOverviewGraphComponent implements AfterViewInit {
|
|||||||
|
|
||||||
start(): void {
|
start(): void {
|
||||||
this.running = true;
|
this.running = true;
|
||||||
this.ngZone.runOutsideAngular(() => this.run());
|
this.ngZone.runOutsideAngular(() => this.doRun());
|
||||||
|
}
|
||||||
|
|
||||||
|
doRun(): void {
|
||||||
|
if (this.animationFrameRequest) {
|
||||||
|
cancelAnimationFrame(this.animationFrameRequest);
|
||||||
|
}
|
||||||
|
this.animationFrameRequest = requestAnimationFrame(() => this.run());
|
||||||
}
|
}
|
||||||
|
|
||||||
run(now?: DOMHighResTimeStamp): void {
|
run(now?: DOMHighResTimeStamp): void {
|
||||||
if (!now) {
|
if (!now) {
|
||||||
now = performance.now();
|
now = performance.now();
|
||||||
}
|
}
|
||||||
|
// skip re-render if there's no change to the scene
|
||||||
|
if (this.scene) {
|
||||||
|
/* SET UP SHADER UNIFORMS */
|
||||||
|
// screen dimensions
|
||||||
|
this.gl.uniform2f(this.gl.getUniformLocation(this.shaderProgram, 'screenSize'), this.displayWidth, this.displayHeight);
|
||||||
|
// frame timestamp
|
||||||
|
this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgram, 'now'), now);
|
||||||
|
|
||||||
/* SET UP SHADER UNIFORMS */
|
if (this.vertexArray.dirty) {
|
||||||
// screen dimensions
|
/* SET UP SHADER ATTRIBUTES */
|
||||||
this.gl.uniform2f(this.gl.getUniformLocation(this.shaderProgram, 'screenSize'), this.displayWidth, this.displayHeight);
|
Object.keys(attribs).forEach((key, i) => {
|
||||||
// frame timestamp
|
this.gl.vertexAttribPointer(attribs[key].pointer,
|
||||||
this.gl.uniform1f(this.gl.getUniformLocation(this.shaderProgram, 'now'), now);
|
attribs[key].count, // number of primitives in this attribute
|
||||||
|
this.gl[attribs[key].type], // type of primitive in this attribute (e.g. gl.FLOAT)
|
||||||
|
false, // never normalised
|
||||||
|
stride, // distance between values of the same attribute
|
||||||
|
attribs[key].offset); // offset of the first value
|
||||||
|
});
|
||||||
|
|
||||||
/* SET UP SHADER ATTRIBUTES */
|
const pointArray = this.vertexArray.getVertexData();
|
||||||
Object.keys(attribs).forEach((key, i) => {
|
|
||||||
this.gl.vertexAttribPointer(attribs[key].pointer,
|
|
||||||
attribs[key].count, // number of primitives in this attribute
|
|
||||||
this.gl[attribs[key].type], // type of primitive in this attribute (e.g. gl.FLOAT)
|
|
||||||
false, // never normalised
|
|
||||||
stride, // distance between values of the same attribute
|
|
||||||
attribs[key].offset); // offset of the first value
|
|
||||||
});
|
|
||||||
|
|
||||||
const pointArray = this.vertexArray.getVertexData();
|
if (pointArray.length) {
|
||||||
|
this.gl.bufferData(this.gl.ARRAY_BUFFER, pointArray, this.gl.DYNAMIC_DRAW);
|
||||||
if (pointArray.length) {
|
this.gl.drawArrays(this.gl.TRIANGLES, 0, pointArray.length / TxSprite.vertexSize);
|
||||||
this.gl.bufferData(this.gl.ARRAY_BUFFER, pointArray, this.gl.DYNAMIC_DRAW);
|
}
|
||||||
this.gl.drawArrays(this.gl.TRIANGLES, 0, pointArray.length / TxSprite.vertexSize);
|
this.vertexArray.dirty = false;
|
||||||
|
} else {
|
||||||
|
const pointArray = this.vertexArray.getVertexData();
|
||||||
|
if (pointArray.length) {
|
||||||
|
this.gl.drawArrays(this.gl.TRIANGLES, 0, pointArray.length / TxSprite.vertexSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* LOOP */
|
/* LOOP */
|
||||||
if (this.running) {
|
if (this.running && this.scene && now <= (this.scene.animateUntil + 500)) {
|
||||||
if (this.animationFrameRequest) {
|
this.doRun();
|
||||||
cancelAnimationFrame(this.animationFrameRequest);
|
} else {
|
||||||
this.animationFrameRequest = null;
|
if (this.animationHeartBeat) {
|
||||||
|
clearTimeout(this.animationHeartBeat);
|
||||||
}
|
}
|
||||||
this.animationFrameRequest = requestAnimationFrame(() => this.run());
|
this.animationHeartBeat = window.setTimeout(() => {
|
||||||
|
this.start();
|
||||||
|
}, 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,11 +280,15 @@ export class BlockOverviewGraphComponent implements AfterViewInit {
|
|||||||
const currentPreview = this.selectedTx || this.hoverTx;
|
const currentPreview = this.selectedTx || this.hoverTx;
|
||||||
|
|
||||||
if (selected !== currentPreview) {
|
if (selected !== currentPreview) {
|
||||||
if (currentPreview) {
|
if (currentPreview && this.scene) {
|
||||||
currentPreview.setHover(false);
|
this.scene.setHover(currentPreview, false);
|
||||||
|
this.start();
|
||||||
}
|
}
|
||||||
if (selected) {
|
if (selected) {
|
||||||
selected.setHover(true);
|
if (selected && this.scene) {
|
||||||
|
this.scene.setHover(selected, true);
|
||||||
|
this.start();
|
||||||
|
}
|
||||||
this.txPreviewEvent.emit({
|
this.txPreviewEvent.emit({
|
||||||
txid: selected.txid,
|
txid: selected.txid,
|
||||||
fee: selected.fee,
|
fee: selected.fee,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { FastVertexArray } from './fast-vertex-array';
|
import { FastVertexArray } from './fast-vertex-array';
|
||||||
import TxView from './tx-view';
|
import TxView from './tx-view';
|
||||||
import { TransactionStripped } from 'src/app/interfaces/websocket.interface';
|
import { TransactionStripped } from 'src/app/interfaces/websocket.interface';
|
||||||
import { Position, Square } from './sprite-types';
|
import { Position, Square, ViewUpdateParams } from './sprite-types';
|
||||||
|
|
||||||
export default class BlockScene {
|
export default class BlockScene {
|
||||||
scene: { count: number, offset: { x: number, y: number}};
|
scene: { count: number, offset: { x: number, y: number}};
|
||||||
@ -19,6 +19,7 @@ export default class BlockScene {
|
|||||||
unitWidth: number;
|
unitWidth: number;
|
||||||
initialised: boolean;
|
initialised: boolean;
|
||||||
layout: BlockLayout;
|
layout: BlockLayout;
|
||||||
|
animateUntil = 0;
|
||||||
dirty: boolean;
|
dirty: boolean;
|
||||||
|
|
||||||
constructor({ width, height, resolution, blockLimit, orientation, flip, vertexArray }:
|
constructor({ width, height, resolution, blockLimit, orientation, flip, vertexArray }:
|
||||||
@ -41,7 +42,7 @@ export default class BlockScene {
|
|||||||
|
|
||||||
this.dirty = true;
|
this.dirty = true;
|
||||||
if (this.initialised && this.scene) {
|
if (this.initialised && this.scene) {
|
||||||
this.updateAll(performance.now());
|
this.updateAll(performance.now(), 50);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,7 +104,7 @@ export default class BlockScene {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.updateAll(startTime, direction);
|
this.updateAll(startTime, 200, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
update(add: TransactionStripped[], remove: string[], direction: string = 'left', resetLayout: boolean = false): void {
|
update(add: TransactionStripped[], remove: string[], direction: string = 'left', resetLayout: boolean = false): void {
|
||||||
@ -139,7 +140,7 @@ export default class BlockScene {
|
|||||||
this.layout.applyGravity();
|
this.layout.applyGravity();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.updateAll(startTime, direction);
|
this.updateAll(startTime, 100, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
// return the tx at this screen position, if any
|
// return the tx at this screen position, if any
|
||||||
@ -152,6 +153,10 @@ export default class BlockScene {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setHover(tx: TxView, value: boolean): void {
|
||||||
|
this.animateUntil = Math.max(this.animateUntil, tx.setHover(value));
|
||||||
|
}
|
||||||
|
|
||||||
private init({ width, height, resolution, blockLimit, orientation, flip, vertexArray }:
|
private init({ width, height, resolution, blockLimit, orientation, flip, vertexArray }:
|
||||||
{ width: number, height: number, resolution: number, blockLimit: number,
|
{ width: number, height: number, resolution: number, blockLimit: number,
|
||||||
orientation: string, flip: boolean, vertexArray: FastVertexArray }
|
orientation: string, flip: boolean, vertexArray: FastVertexArray }
|
||||||
@ -169,7 +174,7 @@ export default class BlockScene {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Set the scale of the visualization (with a 5% margin)
|
// Set the scale of the visualization (with a 5% margin)
|
||||||
this.vbytesPerUnit = blockLimit / Math.pow(resolution / 1.05, 2);
|
this.vbytesPerUnit = blockLimit / Math.pow(resolution / 1.02, 2);
|
||||||
this.gridWidth = resolution;
|
this.gridWidth = resolution;
|
||||||
this.gridHeight = resolution;
|
this.gridHeight = resolution;
|
||||||
this.resize({ width, height });
|
this.resize({ width, height });
|
||||||
@ -181,23 +186,21 @@ export default class BlockScene {
|
|||||||
this.dirty = true;
|
this.dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private insert(tx: TxView, startTime: number, direction: string = 'left'): void {
|
private applyTxUpdate(tx: TxView, update: ViewUpdateParams): void {
|
||||||
this.txs[tx.txid] = tx;
|
this.animateUntil = Math.max(this.animateUntil, tx.update(update));
|
||||||
this.place(tx);
|
|
||||||
this.updateTx(tx, startTime, direction);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateTx(tx: TxView, startTime: number, direction: string = 'left'): void {
|
private updateTx(tx: TxView, startTime: number, delay: number, direction: string = 'left'): void {
|
||||||
if (tx.dirty || this.dirty) {
|
if (tx.dirty || this.dirty) {
|
||||||
this.saveGridToScreenPosition(tx);
|
this.saveGridToScreenPosition(tx);
|
||||||
this.setTxOnScreen(tx, startTime, direction);
|
this.setTxOnScreen(tx, startTime, delay, direction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private setTxOnScreen(tx: TxView, startTime: number, direction: string = 'left'): void {
|
private setTxOnScreen(tx: TxView, startTime: number, delay: number = 50, direction: string = 'left'): void {
|
||||||
if (!tx.initialised) {
|
if (!tx.initialised) {
|
||||||
const txColor = tx.getColor();
|
const txColor = tx.getColor();
|
||||||
tx.update({
|
this.applyTxUpdate(tx, {
|
||||||
display: {
|
display: {
|
||||||
position: {
|
position: {
|
||||||
x: tx.screenPosition.x + (direction === 'right' ? -this.width : (direction === 'left' ? this.width : 0)) * 1.4,
|
x: tx.screenPosition.x + (direction === 'right' ? -this.width : (direction === 'left' ? this.width : 0)) * 1.4,
|
||||||
@ -209,35 +212,35 @@ export default class BlockScene {
|
|||||||
start: startTime,
|
start: startTime,
|
||||||
delay: 0,
|
delay: 0,
|
||||||
});
|
});
|
||||||
tx.update({
|
this.applyTxUpdate(tx, {
|
||||||
display: {
|
display: {
|
||||||
position: tx.screenPosition,
|
position: tx.screenPosition,
|
||||||
color: txColor
|
color: txColor
|
||||||
},
|
},
|
||||||
duration: 1000,
|
duration: 1000,
|
||||||
start: startTime,
|
start: startTime,
|
||||||
delay: 50,
|
delay,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
tx.update({
|
this.applyTxUpdate(tx, {
|
||||||
display: {
|
display: {
|
||||||
position: tx.screenPosition
|
position: tx.screenPosition
|
||||||
},
|
},
|
||||||
duration: 1000,
|
duration: 1000,
|
||||||
minDuration: 500,
|
minDuration: 500,
|
||||||
start: startTime,
|
start: startTime,
|
||||||
delay: 50,
|
delay,
|
||||||
adjust: true
|
adjust: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateAll(startTime: number, direction: string = 'left'): void {
|
private updateAll(startTime: number, delay: number = 50, direction: string = 'left'): void {
|
||||||
this.scene.count = 0;
|
this.scene.count = 0;
|
||||||
const ids = this.getTxList();
|
const ids = this.getTxList();
|
||||||
startTime = startTime || performance.now();
|
startTime = startTime || performance.now();
|
||||||
for (const id of ids) {
|
for (const id of ids) {
|
||||||
this.updateTx(this.txs[id], startTime, direction);
|
this.updateTx(this.txs[id], startTime, delay, direction);
|
||||||
}
|
}
|
||||||
this.dirty = false;
|
this.dirty = false;
|
||||||
}
|
}
|
||||||
@ -246,7 +249,7 @@ export default class BlockScene {
|
|||||||
const tx = this.txs[id];
|
const tx = this.txs[id];
|
||||||
if (tx) {
|
if (tx) {
|
||||||
this.layout.remove(tx);
|
this.layout.remove(tx);
|
||||||
tx.update({
|
this.applyTxUpdate(tx, {
|
||||||
display: {
|
display: {
|
||||||
position: {
|
position: {
|
||||||
x: tx.screenPosition.x + (direction === 'right' ? this.width : (direction === 'left' ? -this.width : 0)) * 1.4,
|
x: tx.screenPosition.x + (direction === 'right' ? this.width : (direction === 'left' ? -this.width : 0)) * 1.4,
|
||||||
@ -319,7 +322,7 @@ export default class BlockScene {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
screenToGrid(position: Position): Position {
|
private screenToGrid(position: Position): Position {
|
||||||
let x = position.x;
|
let x = position.x;
|
||||||
let y = this.height - position.y;
|
let y = this.height - position.y;
|
||||||
let t;
|
let t;
|
||||||
|
@ -18,6 +18,7 @@ export class FastVertexArray {
|
|||||||
data: Float32Array;
|
data: Float32Array;
|
||||||
freeSlots: number[];
|
freeSlots: number[];
|
||||||
lastSlot: number;
|
lastSlot: number;
|
||||||
|
dirty = false;
|
||||||
|
|
||||||
constructor(length, stride) {
|
constructor(length, stride) {
|
||||||
this.length = length;
|
this.length = length;
|
||||||
@ -27,6 +28,7 @@ export class FastVertexArray {
|
|||||||
this.data = new Float32Array(this.length * this.stride);
|
this.data = new Float32Array(this.length * this.stride);
|
||||||
this.freeSlots = [];
|
this.freeSlots = [];
|
||||||
this.lastSlot = 0;
|
this.lastSlot = 0;
|
||||||
|
this.dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
insert(sprite: TxSprite): number {
|
insert(sprite: TxSprite): number {
|
||||||
@ -44,6 +46,7 @@ export class FastVertexArray {
|
|||||||
}
|
}
|
||||||
this.sprites[position] = sprite;
|
this.sprites[position] = sprite;
|
||||||
return position;
|
return position;
|
||||||
|
this.dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
remove(index: number): void {
|
remove(index: number): void {
|
||||||
@ -54,14 +57,17 @@ export class FastVertexArray {
|
|||||||
if (this.length > 2048 && this.count < (this.length * 0.4)) {
|
if (this.length > 2048 && this.count < (this.length * 0.4)) {
|
||||||
this.compact();
|
this.compact();
|
||||||
}
|
}
|
||||||
|
this.dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
setData(index: number, dataChunk: number[]): void {
|
setData(index: number, dataChunk: number[]): void {
|
||||||
this.data.set(dataChunk, (index * this.stride));
|
this.data.set(dataChunk, (index * this.stride));
|
||||||
|
this.dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
clearData(index: number): void {
|
clearData(index: number): void {
|
||||||
this.data.fill(0, (index * this.stride), ((index + 1) * this.stride));
|
this.data.fill(0, (index * this.stride), ((index + 1) * this.stride));
|
||||||
|
this.dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
getData(index: number): Float32Array {
|
getData(index: number): Float32Array {
|
||||||
@ -73,6 +79,7 @@ export class FastVertexArray {
|
|||||||
const newData = new Float32Array(this.length * this.stride);
|
const newData = new Float32Array(this.length * this.stride);
|
||||||
newData.set(this.data);
|
newData.set(this.data);
|
||||||
this.data = newData;
|
this.data = newData;
|
||||||
|
this.dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
compact(): void {
|
compact(): void {
|
||||||
@ -97,6 +104,7 @@ export class FastVertexArray {
|
|||||||
this.freeSlots = [];
|
this.freeSlots = [];
|
||||||
this.lastSlot = i;
|
this.lastSlot = i;
|
||||||
}
|
}
|
||||||
|
this.dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
getVertexData(): Float32Array {
|
getVertexData(): Float32Array {
|
||||||
|
@ -82,8 +82,10 @@ export default class TxView implements TransactionStripped {
|
|||||||
delay: additional milliseconds to wait before starting
|
delay: additional milliseconds to wait before starting
|
||||||
jitter: if set, adds a random amount to the delay,
|
jitter: if set, adds a random amount to the delay,
|
||||||
adjust: if true, modify an in-progress transition instead of replacing it
|
adjust: if true, modify an in-progress transition instead of replacing it
|
||||||
|
|
||||||
|
returns minimum transition end time
|
||||||
*/
|
*/
|
||||||
update(params: ViewUpdateParams): void {
|
update(params: ViewUpdateParams): number {
|
||||||
if (params.jitter) {
|
if (params.jitter) {
|
||||||
params.delay += (Math.random() * params.jitter);
|
params.delay += (Math.random() * params.jitter);
|
||||||
}
|
}
|
||||||
@ -96,6 +98,7 @@ export default class TxView implements TransactionStripped {
|
|||||||
);
|
);
|
||||||
// apply any pending hover event
|
// apply any pending hover event
|
||||||
if (this.hover) {
|
if (this.hover) {
|
||||||
|
params.duration = Math.max(params.duration, hoverTransitionTime);
|
||||||
this.sprite.update({
|
this.sprite.update({
|
||||||
...this.hoverColor,
|
...this.hoverColor,
|
||||||
duration: hoverTransitionTime,
|
duration: hoverTransitionTime,
|
||||||
@ -109,10 +112,12 @@ export default class TxView implements TransactionStripped {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.dirty = false;
|
this.dirty = false;
|
||||||
|
return (params.start || performance.now()) + (params.delay || 0) + (params.duration || 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Temporarily override the tx color
|
// Temporarily override the tx color
|
||||||
setHover(hoverOn: boolean, color: Color | void = defaultHoverColor): void {
|
// returns minimum transition end time
|
||||||
|
setHover(hoverOn: boolean, color: Color | void = defaultHoverColor): number {
|
||||||
if (hoverOn) {
|
if (hoverOn) {
|
||||||
this.hover = true;
|
this.hover = true;
|
||||||
this.hoverColor = color;
|
this.hoverColor = color;
|
||||||
@ -131,6 +136,7 @@ export default class TxView implements TransactionStripped {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.dirty = false;
|
this.dirty = false;
|
||||||
|
return performance.now() + hoverTransitionTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
getColor(): Color {
|
getColor(): Color {
|
||||||
|
@ -216,7 +216,6 @@ export class BlockComponent implements OnInit, OnDestroy {
|
|||||||
return of([]);
|
return of([]);
|
||||||
}),
|
}),
|
||||||
switchMap((transactions) => {
|
switchMap((transactions) => {
|
||||||
console.log('overview loaded: ', prevBlock && prevBlock.height, block.height);
|
|
||||||
if (prevBlock) {
|
if (prevBlock) {
|
||||||
return of({ transactions, direction: (prevBlock.height < block.height) ? 'right' : 'left' });
|
return of({ transactions, direction: (prevBlock.height < block.height) ? 'right' : 'left' });
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user