mirror of
https://github.com/mempool/mempool.git
synced 2024-11-19 09:52:14 +01:00
Merge pull request #3621 from mempool/mononaut/sharper-blocks
Pixel-aligned grids for sharper block visualizations
This commit is contained in:
commit
0ec98d03e5
@ -1,15 +1,17 @@
|
||||
<div class="block-overview-graph">
|
||||
<canvas class="block-overview-canvas" [class.clickable]="!!hoverTx" #blockCanvas></canvas>
|
||||
<div class="loader-wrapper" [class.hidden]="(!isLoading || disableSpinner) && !unavailable">
|
||||
<div *ngIf="isLoading" class="spinner-border ml-3 loading" role="status"></div>
|
||||
<div *ngIf="!isLoading && unavailable" class="ml-3" i18n="block.not-available">not available</div>
|
||||
</div>
|
||||
|
||||
<app-block-overview-tooltip
|
||||
[tx]="selectedTx || hoverTx"
|
||||
[cursorPosition]="tooltipPosition"
|
||||
[clickable]="!!selectedTx"
|
||||
[auditEnabled]="auditHighlighting"
|
||||
[blockConversion]="blockConversion"
|
||||
></app-block-overview-tooltip>
|
||||
<div class="grid-align" [style.gridTemplateColumns]="'repeat(auto-fit, ' + resolution + 'px)'">
|
||||
<div class="block-overview-graph">
|
||||
<canvas class="block-overview-canvas" [class.clickable]="!!hoverTx" #blockCanvas></canvas>
|
||||
<div class="loader-wrapper" [class.hidden]="(!isLoading || disableSpinner) && !unavailable">
|
||||
<div *ngIf="isLoading" class="spinner-border ml-3 loading" role="status"></div>
|
||||
<div *ngIf="!isLoading && unavailable" class="ml-3" i18n="block.not-available">not available</div>
|
||||
</div>
|
||||
<app-block-overview-tooltip
|
||||
[tx]="selectedTx || hoverTx"
|
||||
[cursorPosition]="tooltipPosition"
|
||||
[clickable]="!!selectedTx"
|
||||
[auditEnabled]="auditHighlighting"
|
||||
[blockConversion]="blockConversion"
|
||||
></app-block-overview-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -6,8 +6,16 @@
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
grid-column: 1/-1;
|
||||
}
|
||||
|
||||
.grid-align {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, 75px);
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.block-overview-canvas {
|
||||
position: absolute;
|
||||
|
@ -25,7 +25,6 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
|
||||
@Input() unavailable: boolean = false;
|
||||
@Input() auditHighlighting: boolean = false;
|
||||
@Input() blockConversion: Price;
|
||||
@Input() pixelAlign: boolean = false;
|
||||
@Output() txClickEvent = new EventEmitter<{ tx: TransactionStripped, keyModifier: boolean}>();
|
||||
@Output() txHoverEvent = new EventEmitter<string>();
|
||||
@Output() readyEvent = new EventEmitter();
|
||||
@ -219,7 +218,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On
|
||||
} 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,
|
||||
highlighting: this.auditHighlighting, pixelAlign: this.pixelAlign });
|
||||
highlighting: this.auditHighlighting });
|
||||
this.start();
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ export default class BlockScene {
|
||||
gridWidth: number;
|
||||
gridHeight: number;
|
||||
gridSize: number;
|
||||
pixelAlign: boolean;
|
||||
vbytesPerUnit: number;
|
||||
unitPadding: number;
|
||||
unitWidth: number;
|
||||
@ -24,24 +23,19 @@ export default class BlockScene {
|
||||
animateUntil = 0;
|
||||
dirty: boolean;
|
||||
|
||||
constructor({ width, height, resolution, blockLimit, orientation, flip, vertexArray, highlighting, pixelAlign }:
|
||||
constructor({ width, height, resolution, blockLimit, orientation, flip, vertexArray, highlighting }:
|
||||
{ width: number, height: number, resolution: number, blockLimit: number,
|
||||
orientation: string, flip: boolean, vertexArray: FastVertexArray, highlighting: boolean, pixelAlign: boolean }
|
||||
orientation: string, flip: boolean, vertexArray: FastVertexArray, highlighting: boolean }
|
||||
) {
|
||||
this.init({ width, height, resolution, blockLimit, orientation, flip, vertexArray, highlighting, pixelAlign });
|
||||
this.init({ width, height, resolution, blockLimit, orientation, flip, vertexArray, highlighting });
|
||||
}
|
||||
|
||||
resize({ width = this.width, height = this.height, animate = true }: { width?: number, height?: number, animate: boolean }): void {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.gridSize = this.width / this.gridWidth;
|
||||
if (this.pixelAlign) {
|
||||
this.unitPadding = Math.max(1, Math.floor(this.gridSize / 2.5));
|
||||
this.unitWidth = this.gridSize - (this.unitPadding);
|
||||
} else {
|
||||
this.unitPadding = width / 500;
|
||||
this.unitWidth = this.gridSize - (this.unitPadding * 2);
|
||||
}
|
||||
this.unitPadding = Math.max(1, Math.floor(this.gridSize / 5));
|
||||
this.unitWidth = this.gridSize - (this.unitPadding * 2);
|
||||
|
||||
this.dirty = true;
|
||||
if (this.initialised && this.scene) {
|
||||
@ -219,15 +213,14 @@ export default class BlockScene {
|
||||
this.animateUntil = Math.max(this.animateUntil, tx.setHighlight(value));
|
||||
}
|
||||
|
||||
private init({ width, height, resolution, blockLimit, orientation, flip, vertexArray, highlighting, pixelAlign }:
|
||||
private init({ width, height, resolution, blockLimit, orientation, flip, vertexArray, highlighting }:
|
||||
{ width: number, height: number, resolution: number, blockLimit: number,
|
||||
orientation: string, flip: boolean, vertexArray: FastVertexArray, highlighting: boolean, pixelAlign: boolean }
|
||||
orientation: string, flip: boolean, vertexArray: FastVertexArray, highlighting: boolean }
|
||||
): void {
|
||||
this.orientation = orientation;
|
||||
this.flip = flip;
|
||||
this.vertexArray = vertexArray;
|
||||
this.highlightingEnabled = highlighting;
|
||||
this.pixelAlign = pixelAlign;
|
||||
|
||||
this.scene = {
|
||||
count: 0,
|
||||
@ -353,12 +346,7 @@ export default class BlockScene {
|
||||
private gridToScreen(position: Square | void): Square {
|
||||
if (position) {
|
||||
const slotSize = (position.s * this.gridSize);
|
||||
let squareSize;
|
||||
if (this.pixelAlign) {
|
||||
squareSize = slotSize - (this.unitPadding);
|
||||
} else {
|
||||
squareSize = slotSize - (this.unitPadding * 2);
|
||||
}
|
||||
const squareSize = slotSize - (this.unitPadding * 2);
|
||||
|
||||
// The grid is laid out notionally left-to-right, bottom-to-top,
|
||||
// so we rotate and/or flip the y axis to match the target configuration.
|
||||
@ -434,7 +422,7 @@ export default class BlockScene {
|
||||
|
||||
// calculates and returns the size of the tx in multiples of the grid size
|
||||
private txSize(tx: TxView): number {
|
||||
const scale = Math.max(1, Math.round(Math.sqrt(tx.vsize / this.vbytesPerUnit)));
|
||||
const scale = Math.max(1, Math.round(Math.sqrt(1.1 * tx.vsize / this.vbytesPerUnit)));
|
||||
return Math.min(this.gridWidth, Math.max(1, scale)); // bound between 1 and the max displayable size (just in case!)
|
||||
}
|
||||
|
||||
|
@ -71,7 +71,7 @@
|
||||
<app-block-overview-graph
|
||||
#blockGraph
|
||||
[isLoading]="false"
|
||||
[resolution]="75"
|
||||
[resolution]="80"
|
||||
[blockLimit]="stateService.blockVSize"
|
||||
[orientation]="'top'"
|
||||
[flip]="false"
|
||||
|
@ -52,8 +52,8 @@
|
||||
.chart-container {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
width: 470px;
|
||||
min-width: 470px;
|
||||
width: 480px;
|
||||
min-width: 480px;
|
||||
padding: 0;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
@ -100,7 +100,7 @@
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="col-sm" [class.graph-col]="webGlEnabled && !showAudit">
|
||||
<table class="table table-borderless table-striped" *ngIf="!isMobile && !(webGlEnabled && !showAudit)">
|
||||
<tbody>
|
||||
<ng-container *ngTemplateOutlet="restOfTable"></ng-container>
|
||||
@ -110,7 +110,7 @@
|
||||
<app-block-overview-graph
|
||||
#blockGraphActual
|
||||
[isLoading]="isLoadingOverview"
|
||||
[resolution]="75"
|
||||
[resolution]="86"
|
||||
[blockLimit]="stateService.blockVSize"
|
||||
[orientation]="'top'"
|
||||
[flip]="false"
|
||||
@ -227,7 +227,7 @@
|
||||
<div class="col-sm">
|
||||
<h3 class="block-subtitle" *ngIf="!isMobile"><ng-container i18n="block.expected-block">Expected Block</ng-container> <span class="badge badge-pill badge-warning beta" i18n="beta">beta</span></h3>
|
||||
<div class="block-graph-wrapper">
|
||||
<app-block-overview-graph #blockGraphProjected [isLoading]="isLoadingOverview" [resolution]="75"
|
||||
<app-block-overview-graph #blockGraphProjected [isLoading]="isLoadingOverview" [resolution]="86"
|
||||
[blockLimit]="stateService.blockVSize" [orientation]="'top'" [flip]="false" [mirrorTxid]="hoverTx" [auditHighlighting]="showAudit"
|
||||
(txClickEvent)="onTxClick($event)" (txHoverEvent)="onTxHover($event)" [unavailable]="!isMobile && !showAudit"></app-block-overview-graph>
|
||||
<ng-container *ngIf="!isMobile || mode !== 'actual'; else emptyBlockInfo"></ng-container>
|
||||
@ -239,7 +239,7 @@
|
||||
<div class="col-sm" *ngIf="!isMobile">
|
||||
<h3 class="block-subtitle actual" *ngIf="!isMobile"><ng-container i18n="block.actual-block">Actual Block</ng-container> <a class="info-link" [routerLink]="['/docs/faq' | relativeUrl ]" fragment="how-do-block-audits-work"><fa-icon [icon]="['fas', 'info-circle']" [fixedWidth]="true"></fa-icon></a></h3>
|
||||
<div class="block-graph-wrapper">
|
||||
<app-block-overview-graph #blockGraphActual [isLoading]="isLoadingOverview" [resolution]="75"
|
||||
<app-block-overview-graph #blockGraphActual [isLoading]="isLoadingOverview" [resolution]="86"
|
||||
[blockLimit]="stateService.blockVSize" [orientation]="'top'" [flip]="false" [mirrorTxid]="hoverTx" mode="mined" [auditHighlighting]="showAudit"
|
||||
(txClickEvent)="onTxClick($event)" (txHoverEvent)="onTxHover($event)" [unavailable]="isMobile && !showAudit"></app-block-overview-graph>
|
||||
<ng-container *ngTemplateOutlet="emptyBlockInfo"></ng-container>
|
||||
|
@ -239,6 +239,7 @@ h1 {
|
||||
.nav-tabs {
|
||||
border-color: white;
|
||||
border-width: 1px;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.nav-tabs .nav-link {
|
||||
@ -293,3 +294,7 @@ h1 {
|
||||
margin-top: 0.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
.graph-col {
|
||||
flex-grow: 1.11;
|
||||
}
|
||||
|
@ -25,7 +25,7 @@
|
||||
</ng-container>
|
||||
<ng-template #mempoolMode>
|
||||
<div class="block-sizer" [style]="blockSizerStyle">
|
||||
<app-mempool-block-overview [index]="blockIndex" [pixelAlign]="true"></app-mempool-block-overview>
|
||||
<app-mempool-block-overview [index]="blockIndex"></app-mempool-block-overview>
|
||||
</div>
|
||||
</ng-template>
|
||||
<div class="fader"></div>
|
||||
|
@ -1,10 +1,9 @@
|
||||
<app-block-overview-graph
|
||||
#blockGraph
|
||||
[isLoading]="isLoading$ | async"
|
||||
[resolution]="75"
|
||||
[resolution]="86"
|
||||
[blockLimit]="stateService.blockVSize"
|
||||
[orientation]="timeLtr ? 'right' : 'left'"
|
||||
[flip]="true"
|
||||
[pixelAlign]="pixelAlign"
|
||||
(txClickEvent)="onTxClick($event)"
|
||||
></app-block-overview-graph>
|
||||
|
@ -16,7 +16,6 @@ import { Router } from '@angular/router';
|
||||
})
|
||||
export class MempoolBlockOverviewComponent implements OnInit, OnDestroy, OnChanges, AfterViewInit {
|
||||
@Input() index: number;
|
||||
@Input() pixelAlign: boolean = false;
|
||||
@Output() txPreviewEvent = new EventEmitter<TransactionStripped | void>();
|
||||
|
||||
@ViewChild('blockGraph') blockGraph: BlockOverviewGraphComponent;
|
||||
|
Loading…
Reference in New Issue
Block a user