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 { WebsocketService } from 'src/app/services/websocket.service';
 | 
			
		||||
import { FastVertexArray } from './fast-vertex-array';
 | 
			
		||||
@ -11,7 +11,7 @@ import TxView from './tx-view';
 | 
			
		||||
  templateUrl: './block-overview-graph.component.html',
 | 
			
		||||
  styleUrls: ['./block-overview-graph.component.scss'],
 | 
			
		||||
})
 | 
			
		||||
export class BlockOverviewGraphComponent implements AfterViewInit {
 | 
			
		||||
export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy {
 | 
			
		||||
  @Input() isLoading: boolean;
 | 
			
		||||
  @Input() resolution: number;
 | 
			
		||||
  @Input() blockLimit: number;
 | 
			
		||||
@ -24,6 +24,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit {
 | 
			
		||||
 | 
			
		||||
  gl: WebGLRenderingContext;
 | 
			
		||||
  animationFrameRequest: number;
 | 
			
		||||
  animationHeartBeat: number;
 | 
			
		||||
  displayWidth: number;
 | 
			
		||||
  displayHeight: number;
 | 
			
		||||
  cssWidth: number;
 | 
			
		||||
@ -50,34 +51,46 @@ export class BlockOverviewGraphComponent implements AfterViewInit {
 | 
			
		||||
    this.resizeCanvas();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnDestroy(): void {
 | 
			
		||||
    if (this.animationFrameRequest) {
 | 
			
		||||
      cancelAnimationFrame(this.animationFrameRequest);
 | 
			
		||||
      clearTimeout(this.animationHeartBeat);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  clear(direction): void {
 | 
			
		||||
    this.exit(direction);
 | 
			
		||||
    this.hoverTx = null;
 | 
			
		||||
    this.selectedTx = null;
 | 
			
		||||
    this.txPreviewEvent.emit(null);
 | 
			
		||||
    this.start();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  enter(transactions: TransactionStripped[], direction: string): void {
 | 
			
		||||
    if (this.scene) {
 | 
			
		||||
      this.scene.enter(transactions, direction);
 | 
			
		||||
      this.start();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  exit(direction: string): void {
 | 
			
		||||
    if (this.scene) {
 | 
			
		||||
      this.scene.exit(direction);
 | 
			
		||||
      this.start();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  replace(transactions: TransactionStripped[], direction: string, sort: boolean = true): void {
 | 
			
		||||
    if (this.scene) {
 | 
			
		||||
      this.scene.replace(transactions || [], direction, sort);
 | 
			
		||||
      this.start();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  update(add: TransactionStripped[], remove: string[], direction: string = 'left', resetLayout: boolean = false): void {
 | 
			
		||||
    if (this.scene) {
 | 
			
		||||
      this.scene.update(add, remove, direction, resetLayout);
 | 
			
		||||
      this.start();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -140,6 +153,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit {
 | 
			
		||||
    }
 | 
			
		||||
    if (this.scene) {
 | 
			
		||||
      this.scene.resize({ width: this.displayWidth, height: this.displayHeight });
 | 
			
		||||
      this.start();
 | 
			
		||||
    } else {
 | 
			
		||||
      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 });
 | 
			
		||||
@ -182,44 +196,64 @@ export class BlockOverviewGraphComponent implements AfterViewInit {
 | 
			
		||||
 | 
			
		||||
  start(): void {
 | 
			
		||||
    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 {
 | 
			
		||||
    if (!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 */
 | 
			
		||||
    // 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);
 | 
			
		||||
      if (this.vertexArray.dirty) {
 | 
			
		||||
        /* SET UP SHADER ATTRIBUTES */
 | 
			
		||||
        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
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    /* SET UP SHADER ATTRIBUTES */
 | 
			
		||||
    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();
 | 
			
		||||
 | 
			
		||||
    const pointArray = this.vertexArray.getVertexData();
 | 
			
		||||
 | 
			
		||||
    if (pointArray.length) {
 | 
			
		||||
      this.gl.bufferData(this.gl.ARRAY_BUFFER, pointArray, this.gl.DYNAMIC_DRAW);
 | 
			
		||||
      this.gl.drawArrays(this.gl.TRIANGLES, 0, pointArray.length / TxSprite.vertexSize);
 | 
			
		||||
        if (pointArray.length) {
 | 
			
		||||
          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 */
 | 
			
		||||
    if (this.running) {
 | 
			
		||||
      if (this.animationFrameRequest) {
 | 
			
		||||
        cancelAnimationFrame(this.animationFrameRequest);
 | 
			
		||||
        this.animationFrameRequest = null;
 | 
			
		||||
    if (this.running && this.scene && now <= (this.scene.animateUntil + 500)) {
 | 
			
		||||
      this.doRun();
 | 
			
		||||
    } else {
 | 
			
		||||
      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;
 | 
			
		||||
 | 
			
		||||
      if (selected !== currentPreview) {
 | 
			
		||||
        if (currentPreview) {
 | 
			
		||||
          currentPreview.setHover(false);
 | 
			
		||||
        if (currentPreview && this.scene) {
 | 
			
		||||
          this.scene.setHover(currentPreview, false);
 | 
			
		||||
          this.start();
 | 
			
		||||
        }
 | 
			
		||||
        if (selected) {
 | 
			
		||||
          selected.setHover(true);
 | 
			
		||||
          if (selected && this.scene) {
 | 
			
		||||
            this.scene.setHover(selected, true);
 | 
			
		||||
            this.start();
 | 
			
		||||
          }
 | 
			
		||||
          this.txPreviewEvent.emit({
 | 
			
		||||
            txid: selected.txid,
 | 
			
		||||
            fee: selected.fee,
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
import { FastVertexArray } from './fast-vertex-array';
 | 
			
		||||
import TxView from './tx-view';
 | 
			
		||||
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 {
 | 
			
		||||
  scene: { count: number, offset: { x: number, y: number}};
 | 
			
		||||
@ -19,6 +19,7 @@ export default class BlockScene {
 | 
			
		||||
  unitWidth: number;
 | 
			
		||||
  initialised: boolean;
 | 
			
		||||
  layout: BlockLayout;
 | 
			
		||||
  animateUntil = 0;
 | 
			
		||||
  dirty: boolean;
 | 
			
		||||
 | 
			
		||||
  constructor({ width, height, resolution, blockLimit, orientation, flip, vertexArray }:
 | 
			
		||||
@ -41,7 +42,7 @@ export default class BlockScene {
 | 
			
		||||
 | 
			
		||||
    this.dirty = true;
 | 
			
		||||
    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 {
 | 
			
		||||
@ -139,7 +140,7 @@ export default class BlockScene {
 | 
			
		||||
      this.layout.applyGravity();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.updateAll(startTime, direction);
 | 
			
		||||
    this.updateAll(startTime, 100, direction);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // 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 }:
 | 
			
		||||
      { width: number, height: number, resolution: number, blockLimit: number,
 | 
			
		||||
        orientation: string, flip: boolean, vertexArray: FastVertexArray }
 | 
			
		||||
@ -169,7 +174,7 @@ export default class BlockScene {
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // 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.gridHeight = resolution;
 | 
			
		||||
    this.resize({ width, height });
 | 
			
		||||
@ -181,23 +186,21 @@ export default class BlockScene {
 | 
			
		||||
    this.dirty = true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private insert(tx: TxView, startTime: number, direction: string = 'left'): void {
 | 
			
		||||
    this.txs[tx.txid] = tx;
 | 
			
		||||
    this.place(tx);
 | 
			
		||||
    this.updateTx(tx, startTime, direction);
 | 
			
		||||
  private applyTxUpdate(tx: TxView, update: ViewUpdateParams): void {
 | 
			
		||||
    this.animateUntil = Math.max(this.animateUntil, tx.update(update));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  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) {
 | 
			
		||||
      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) {
 | 
			
		||||
      const txColor = tx.getColor();
 | 
			
		||||
      tx.update({
 | 
			
		||||
      this.applyTxUpdate(tx, {
 | 
			
		||||
        display: {
 | 
			
		||||
          position: {
 | 
			
		||||
            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,
 | 
			
		||||
        delay: 0,
 | 
			
		||||
      });
 | 
			
		||||
      tx.update({
 | 
			
		||||
      this.applyTxUpdate(tx, {
 | 
			
		||||
        display: {
 | 
			
		||||
          position: tx.screenPosition,
 | 
			
		||||
          color: txColor
 | 
			
		||||
        },
 | 
			
		||||
        duration: 1000,
 | 
			
		||||
        start: startTime,
 | 
			
		||||
        delay: 50,
 | 
			
		||||
        delay,
 | 
			
		||||
      });
 | 
			
		||||
    } else {
 | 
			
		||||
      tx.update({
 | 
			
		||||
      this.applyTxUpdate(tx, {
 | 
			
		||||
        display: {
 | 
			
		||||
          position: tx.screenPosition
 | 
			
		||||
        },
 | 
			
		||||
        duration: 1000,
 | 
			
		||||
        minDuration: 500,
 | 
			
		||||
        start: startTime,
 | 
			
		||||
        delay: 50,
 | 
			
		||||
        delay,
 | 
			
		||||
        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;
 | 
			
		||||
    const ids = this.getTxList();
 | 
			
		||||
    startTime = startTime || performance.now();
 | 
			
		||||
    for (const id of ids) {
 | 
			
		||||
      this.updateTx(this.txs[id], startTime, direction);
 | 
			
		||||
      this.updateTx(this.txs[id], startTime, delay, direction);
 | 
			
		||||
    }
 | 
			
		||||
    this.dirty = false;
 | 
			
		||||
  }
 | 
			
		||||
@ -246,7 +249,7 @@ export default class BlockScene {
 | 
			
		||||
    const tx = this.txs[id];
 | 
			
		||||
    if (tx) {
 | 
			
		||||
      this.layout.remove(tx);
 | 
			
		||||
      tx.update({
 | 
			
		||||
      this.applyTxUpdate(tx, {
 | 
			
		||||
        display: {
 | 
			
		||||
          position: {
 | 
			
		||||
            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 y = this.height - position.y;
 | 
			
		||||
    let t;
 | 
			
		||||
 | 
			
		||||
@ -18,6 +18,7 @@ export class FastVertexArray {
 | 
			
		||||
  data: Float32Array;
 | 
			
		||||
  freeSlots: number[];
 | 
			
		||||
  lastSlot: number;
 | 
			
		||||
  dirty = false;
 | 
			
		||||
 | 
			
		||||
  constructor(length, stride) {
 | 
			
		||||
    this.length = length;
 | 
			
		||||
@ -27,6 +28,7 @@ export class FastVertexArray {
 | 
			
		||||
    this.data = new Float32Array(this.length * this.stride);
 | 
			
		||||
    this.freeSlots = [];
 | 
			
		||||
    this.lastSlot = 0;
 | 
			
		||||
    this.dirty = true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  insert(sprite: TxSprite): number {
 | 
			
		||||
@ -44,6 +46,7 @@ export class FastVertexArray {
 | 
			
		||||
    }
 | 
			
		||||
    this.sprites[position] = sprite;
 | 
			
		||||
    return position;
 | 
			
		||||
    this.dirty = true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  remove(index: number): void {
 | 
			
		||||
@ -54,14 +57,17 @@ export class FastVertexArray {
 | 
			
		||||
    if (this.length > 2048 && this.count < (this.length * 0.4)) {
 | 
			
		||||
      this.compact();
 | 
			
		||||
    }
 | 
			
		||||
    this.dirty = true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  setData(index: number, dataChunk: number[]): void {
 | 
			
		||||
    this.data.set(dataChunk, (index * this.stride));
 | 
			
		||||
    this.dirty = true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  clearData(index: number): void {
 | 
			
		||||
    this.data.fill(0, (index * this.stride), ((index + 1) * this.stride));
 | 
			
		||||
    this.dirty = true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getData(index: number): Float32Array {
 | 
			
		||||
@ -73,6 +79,7 @@ export class FastVertexArray {
 | 
			
		||||
    const newData = new Float32Array(this.length * this.stride);
 | 
			
		||||
    newData.set(this.data);
 | 
			
		||||
    this.data = newData;
 | 
			
		||||
    this.dirty = true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  compact(): void {
 | 
			
		||||
@ -97,6 +104,7 @@ export class FastVertexArray {
 | 
			
		||||
      this.freeSlots = [];
 | 
			
		||||
      this.lastSlot = i;
 | 
			
		||||
    }
 | 
			
		||||
    this.dirty = true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getVertexData(): Float32Array {
 | 
			
		||||
 | 
			
		||||
@ -82,8 +82,10 @@ export default class TxView implements TransactionStripped {
 | 
			
		||||
    delay: additional milliseconds to wait before starting
 | 
			
		||||
    jitter: if set, adds a random amount to the delay,
 | 
			
		||||
    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) {
 | 
			
		||||
      params.delay += (Math.random() * params.jitter);
 | 
			
		||||
    }
 | 
			
		||||
@ -96,6 +98,7 @@ export default class TxView implements TransactionStripped {
 | 
			
		||||
      );
 | 
			
		||||
      // apply any pending hover event
 | 
			
		||||
      if (this.hover) {
 | 
			
		||||
        params.duration = Math.max(params.duration, hoverTransitionTime);
 | 
			
		||||
        this.sprite.update({
 | 
			
		||||
          ...this.hoverColor,
 | 
			
		||||
          duration: hoverTransitionTime,
 | 
			
		||||
@ -109,10 +112,12 @@ export default class TxView implements TransactionStripped {
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    this.dirty = false;
 | 
			
		||||
    return (params.start || performance.now()) + (params.delay || 0) + (params.duration || 0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // 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) {
 | 
			
		||||
      this.hover = true;
 | 
			
		||||
      this.hoverColor = color;
 | 
			
		||||
@ -131,6 +136,7 @@ export default class TxView implements TransactionStripped {
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    this.dirty = false;
 | 
			
		||||
    return performance.now() + hoverTransitionTime;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getColor(): Color {
 | 
			
		||||
 | 
			
		||||
@ -216,7 +216,6 @@ export class BlockComponent implements OnInit, OnDestroy {
 | 
			
		||||
            return of([]);
 | 
			
		||||
          }),
 | 
			
		||||
          switchMap((transactions) => {
 | 
			
		||||
            console.log('overview loaded: ', prevBlock && prevBlock.height, block.height);
 | 
			
		||||
            if (prevBlock) {
 | 
			
		||||
              return of({ transactions, direction: (prevBlock.height < block.height) ? 'right' : 'left' });
 | 
			
		||||
            } else {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user