make accelerations magical again
This commit is contained in:
		
							parent
							
								
									fc5b99f93f
								
							
						
					
					
						commit
						b8cfeb579b
					
				| @ -0,0 +1,5 @@ | ||||
| <div class="sparkles" #sparkleAnchor> | ||||
|   <div *ngFor="let sparkle of sparkles" class="sparkle" [style]="sparkle.style"> | ||||
|     <span class="inner-sparkle" [style]="sparkle.rotation">+</span> | ||||
|   </div> | ||||
| </div> | ||||
| @ -0,0 +1,45 @@ | ||||
| .sparkles { | ||||
|   position: absolute; | ||||
|   top: var(--block-size); | ||||
|   height: 50px; | ||||
|   right: 0; | ||||
| } | ||||
| 
 | ||||
| .sparkle { | ||||
|   position: absolute; | ||||
|   color: rgba(152, 88, 255, 0.75); | ||||
|   opacity: 0; | ||||
|   transform: scale(0.8) rotate(0deg); | ||||
|   animation: pop ease 2000ms forwards, sparkle ease 500ms infinite; | ||||
| } | ||||
| 
 | ||||
| .inner-sparkle { | ||||
|   display: block; | ||||
| } | ||||
| 
 | ||||
| @keyframes pop { | ||||
|   0% { | ||||
|     transform: scale(0.8) rotate(0deg); | ||||
|     opacity: 0; | ||||
|   } | ||||
|   20% { | ||||
|     transform: scale(1) rotate(72deg); | ||||
|     opacity: 1; | ||||
|   } | ||||
|   100% { | ||||
|     transform: scale(0) rotate(360deg); | ||||
|     opacity: 0; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| @keyframes sparkle { | ||||
|   0% { | ||||
|     color: rgba(152, 88, 255, 0.75); | ||||
|   } | ||||
|   50% { | ||||
|     color: rgba(198, 162, 255, 0.75); | ||||
|   } | ||||
|   100% { | ||||
|     color: rgba(152, 88, 255, 0.75); | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,71 @@ | ||||
| import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, Input, OnChanges, SimpleChanges, ViewChild } from '@angular/core'; | ||||
| 
 | ||||
| @Component({ | ||||
|   selector: 'app-acceleration-sparkles', | ||||
|   templateUrl: './acceleration-sparkles.component.html', | ||||
|   styleUrls: ['./acceleration-sparkles.component.scss'], | ||||
|   changeDetection: ChangeDetectionStrategy.OnPush, | ||||
| }) | ||||
| export class AccelerationSparklesComponent implements OnChanges { | ||||
|   @Input() arrow: ElementRef<HTMLDivElement>; | ||||
|   @Input() run: boolean = false; | ||||
| 
 | ||||
|   @ViewChild('sparkleAnchor') | ||||
|   sparkleAnchor: ElementRef<HTMLDivElement>; | ||||
| 
 | ||||
|   constructor( | ||||
|     private cd: ChangeDetectorRef, | ||||
|   ) {} | ||||
| 
 | ||||
|   endTimeout: any; | ||||
|   lastSparkle: number = 0; | ||||
|   sparkleWidth: number = 0; | ||||
|   sparkles: any[] = []; | ||||
| 
 | ||||
|   ngOnChanges(changes: SimpleChanges): void { | ||||
|     if (changes.run) { | ||||
|       if (this.endTimeout) { | ||||
|         clearTimeout(this.endTimeout); | ||||
|         this.endTimeout = null; | ||||
|       } | ||||
|       if (this.run) { | ||||
|         this.doSparkle(); | ||||
|       } else { | ||||
|         this.endTimeout = setTimeout(() => { | ||||
|           this.sparkles = []; | ||||
|         }, 2000); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   doSparkle(): void { | ||||
|     if (this.run) { | ||||
|       const now = performance.now(); | ||||
|       if (now - this.lastSparkle > 30) { | ||||
|         this.lastSparkle = now; | ||||
|         if (this.arrow?.nativeElement && this.sparkleAnchor?.nativeElement) { | ||||
|           const anchor = this.sparkleAnchor.nativeElement.getBoundingClientRect().right; | ||||
|           const right = this.arrow.nativeElement.getBoundingClientRect().right; | ||||
|           const dx = (anchor - right) + 37.5; | ||||
|           this.sparkles.push({ | ||||
|             style: { | ||||
|               right: dx + 'px', | ||||
|               top: (Math.random() * 30) + 'px', | ||||
|               animationDelay: (Math.random() * 50) + 'ms', | ||||
|             }, | ||||
|             rotation: { | ||||
|               transform: `rotate(${Math.random() * 360}deg)`, | ||||
|             } | ||||
|           }); | ||||
|           while (this.sparkles.length > 100) { | ||||
|             this.sparkles.shift(); | ||||
|           } | ||||
|           this.cd.markForCheck(); | ||||
|         } | ||||
|       } | ||||
|       requestAnimationFrame(() => { | ||||
|         this.doSparkle(); | ||||
|       }); | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @ -51,7 +51,8 @@ | ||||
|         </div> | ||||
|       </ng-template> | ||||
|     </div> | ||||
|     <div *ngIf="arrowVisible" id="arrow-up" [ngStyle]="{'right': rightPosition + (blockWidth * 0.3) + containerOffset + 'px', transition: transition }" [class.blink]="txPosition?.accelerated"></div> | ||||
|     <app-acceleration-sparkles [style]="{ position: 'absolute', right: 0}" [arrow]="arrowElement" [run]="acceleratingArrow"></app-acceleration-sparkles> | ||||
|     <div *ngIf="arrowVisible" #arrowUp id="arrow-up" [ngStyle]="{'right': rightPosition + (blockWidth * 0.3) + containerOffset + 'px', transition: transition }" [class.blink]="txPosition?.accelerated"></div> | ||||
|   </div> | ||||
| </ng-container> | ||||
| 
 | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, ChangeDetectorRef, HostListener, Input, OnChanges, SimpleChanges, Output, EventEmitter } from '@angular/core'; | ||||
| import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, ChangeDetectorRef, HostListener, Input, OnChanges, SimpleChanges, Output, EventEmitter, ViewChild, ElementRef } from '@angular/core'; | ||||
| import { Subscription, Observable, of, combineLatest } from 'rxjs'; | ||||
| import { MempoolBlock } from '../../interfaces/websocket.interface'; | ||||
| import { StateService } from '../../services/state.service'; | ||||
| @ -77,6 +77,9 @@ export class MempoolBlocksComponent implements OnInit, OnChanges, OnDestroy { | ||||
|   maxArrowPosition = 0; | ||||
|   rightPosition = 0; | ||||
|   transition = 'background 2s, right 2s, transform 1s'; | ||||
|   @ViewChild('arrowUp') | ||||
|   arrowElement: ElementRef<HTMLDivElement>; | ||||
|   acceleratingArrow: boolean = false; | ||||
| 
 | ||||
|   markIndex: number; | ||||
|   txPosition: MempoolPosition; | ||||
| @ -201,6 +204,7 @@ export class MempoolBlocksComponent implements OnInit, OnChanges, OnDestroy { | ||||
| 
 | ||||
|     this.markBlocksSubscription = this.stateService.markBlock$ | ||||
|       .subscribe((state) => { | ||||
|         const oldTxPosition = this.txPosition; | ||||
|         this.markIndex = undefined; | ||||
|         this.txPosition = undefined; | ||||
|         this.txFeePerVSize = undefined; | ||||
| @ -209,6 +213,12 @@ export class MempoolBlocksComponent implements OnInit, OnChanges, OnDestroy { | ||||
|         } | ||||
|         if (state.mempoolPosition) { | ||||
|           this.txPosition = state.mempoolPosition; | ||||
|           if (this.txPosition.accelerated && !oldTxPosition.accelerated) { | ||||
|             this.acceleratingArrow = true; | ||||
|             setTimeout(() => { | ||||
|               this.acceleratingArrow = false; | ||||
|             }, 2000); | ||||
|           } | ||||
|         } | ||||
|         if (state.txFeePerVSize) { | ||||
|           this.txFeePerVSize = state.txFeePerVSize; | ||||
|  | ||||
| @ -100,6 +100,7 @@ import { MempoolErrorComponent } from './components/mempool-error/mempool-error. | ||||
| import { AccelerationsListComponent } from '../components/acceleration/accelerations-list/accelerations-list.component'; | ||||
| import { PendingStatsComponent } from '../components/acceleration/pending-stats/pending-stats.component'; | ||||
| import { AccelerationStatsComponent } from '../components/acceleration/acceleration-stats/acceleration-stats.component'; | ||||
| import { AccelerationSparklesComponent } from '../components/acceleration/sparkles/acceleration-sparkles.component'; | ||||
| 
 | ||||
| import { BlockViewComponent } from '../components/block-view/block-view.component'; | ||||
| import { EightBlocksComponent } from '../components/eight-blocks/eight-blocks.component'; | ||||
| @ -225,6 +226,7 @@ import { OnlyVsizeDirective, OnlyWeightDirective } from './components/weight-dir | ||||
|     AccelerationsListComponent, | ||||
|     AccelerationStatsComponent, | ||||
|     PendingStatsComponent, | ||||
|     AccelerationSparklesComponent, | ||||
|     HttpErrorComponent, | ||||
|     TwitterWidgetComponent, | ||||
|     FaucetComponent, | ||||
| @ -355,6 +357,7 @@ import { OnlyVsizeDirective, OnlyWeightDirective } from './components/weight-dir | ||||
|     AccelerationsListComponent, | ||||
|     AccelerationStatsComponent, | ||||
|     PendingStatsComponent, | ||||
|     AccelerationSparklesComponent, | ||||
|     HttpErrorComponent, | ||||
|     TwitterWidgetComponent, | ||||
|     TwitterLogin, | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user