Improve Brand Accent Renderer

This commit is contained in:
copecone committed 2026-04-17 11:38:34 +09:00
1 parent 0801ed3c70
commit 02f936b345
1 file changed
+18 -26
+18 -26
View File
@@ -6,7 +6,7 @@ import {
inject, inject,
NgZone, NgZone,
OnDestroy, OnDestroy,
ViewChild, viewChild,
} from '@angular/core'; } from '@angular/core';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { SettingsService } from '../../services/settings.service'; import { SettingsService } from '../../services/settings.service';
@@ -19,7 +19,7 @@ import { SettingsService } from '../../services/settings.service';
styleUrl: './brand-accent.scss', styleUrl: './brand-accent.scss',
}) })
export class BrandAccent implements OnDestroy { export class BrandAccent implements OnDestroy {
@ViewChild('canvasElement') canvasRef!: ElementRef<HTMLCanvasElement>; canvasRef = viewChild<ElementRef<HTMLCanvasElement>>('canvasElement');
private ctx!: CanvasRenderingContext2D; private ctx!: CanvasRenderingContext2D;
private settingsService = inject(SettingsService); private settingsService = inject(SettingsService);
@@ -27,8 +27,8 @@ export class BrandAccent implements OnDestroy {
private bgGradient!: CanvasGradient; private bgGradient!: CanvasGradient;
private gridGradient!: CanvasGradient; private gridGradient!: CanvasGradient;
private offscreenCanvas!: OffscreenCanvas; private readonly offscreenCanvas!: OffscreenCanvas;
private offscreenCtx!: OffscreenCanvasRenderingContext2D; private readonly offscreenCtx!: OffscreenCanvasRenderingContext2D;
private resizeObserver?: ResizeObserver; private resizeObserver?: ResizeObserver;
private intersectionObserver?: IntersectionObserver; private intersectionObserver?: IntersectionObserver;
@@ -68,7 +68,10 @@ export class BrandAccent implements OnDestroy {
}); });
afterNextRender(() => { afterNextRender(() => {
this.ctx = this.canvasRef.nativeElement.getContext('2d', { colorSpace: 'srgb' })!; const nativeElement = this.canvasRef()?.nativeElement;
if (nativeElement) {
this.ctx = nativeElement.getContext('2d', { colorSpace: 'srgb' })!;
this.ngZone.runOutsideAngular(() => { this.ngZone.runOutsideAngular(() => {
this.resizeObserver = new ResizeObserver((entries) => { this.resizeObserver = new ResizeObserver((entries) => {
@@ -77,7 +80,7 @@ export class BrandAccent implements OnDestroy {
this.resize(width, height); this.resize(width, height);
} }
}); });
this.resizeObserver.observe(this.canvasRef.nativeElement); this.resizeObserver.observe(nativeElement);
this.intersectionObserver = new IntersectionObserver( this.intersectionObserver = new IntersectionObserver(
(entries) => { (entries) => {
@@ -90,22 +93,23 @@ export class BrandAccent implements OnDestroy {
}, },
{ rootMargin: '200px' }, { rootMargin: '200px' },
); );
this.intersectionObserver.observe(this.canvasRef.nativeElement); this.intersectionObserver.observe(nativeElement);
// Safe Initialization // Safe Initialization
const rect = this.canvasRef.nativeElement.getBoundingClientRect(); const rect = nativeElement.getBoundingClientRect();
this.resize(rect.width, rect.height); this.resize(rect.width, rect.height);
this.animation.startTime = performance.now(); this.animation.startTime = performance.now();
this.draw(); this.draw();
// this.animate(performance.now()); // this.animate(performance.now());
}); });
}
}); });
} }
private resize(width: number, height: number) { private resize(width: number, height: number) {
const canvas = this.canvasRef.nativeElement; const canvas = this.canvasRef()?.nativeElement;
if (canvas) {
const dpr = window.devicePixelRatio || 1; const dpr = window.devicePixelRatio || 1;
this.rendererScale = dpr; this.rendererScale = dpr;
@@ -118,19 +122,15 @@ export class BrandAccent implements OnDestroy {
this.offscreenCanvas.height = height; this.offscreenCanvas.height = height;
} }
this.canvasNativeSize = [width, height];
this.ctx.scale(dpr, dpr); this.ctx.scale(dpr, dpr);
this.updateAnimationInfo(); this.updateAnimationInfo();
this.animate(performance.now());
this.update(performance.now()); }
this.draw();
} }
private updateAnimationInfo() { private updateAnimationInfo() {
this.canvasNativeSize = [
this.canvasRef.nativeElement.clientWidth,
this.canvasRef.nativeElement.clientHeight,
];
this.animation.gridDimension = [ this.animation.gridDimension = [
Math.trunc(this.canvasNativeSize[0] / this.animation.gridSquareSize) + 3, Math.trunc(this.canvasNativeSize[0] / this.animation.gridSquareSize) + 3,
Math.trunc(this.canvasNativeSize[1] / this.animation.gridSquareSize) + 3, Math.trunc(this.canvasNativeSize[1] / this.animation.gridSquareSize) + 3,
@@ -209,14 +209,6 @@ export class BrandAccent implements OnDestroy {
private animate = (currentTime: number) => { private animate = (currentTime: number) => {
this.animation.id = requestAnimationFrame(this.animate); this.animation.id = requestAnimationFrame(this.animate);
const canvas = this.canvasRef.nativeElement;
if (
canvas.clientWidth !== this.canvasNativeSize[0] ||
canvas.clientHeight !== this.canvasNativeSize[1]
) {
return;
}
this.update(currentTime); this.update(currentTime);
this.draw(); this.draw();
}; };