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
+50 -58
+50 -58
View File
@@ -6,7 +6,7 @@ import {
inject,
NgZone,
OnDestroy,
ViewChild,
viewChild,
} from '@angular/core';
import { CommonModule } from '@angular/common';
import { SettingsService } from '../../services/settings.service';
@@ -19,7 +19,7 @@ import { SettingsService } from '../../services/settings.service';
styleUrl: './brand-accent.scss',
})
export class BrandAccent implements OnDestroy {
@ViewChild('canvasElement') canvasRef!: ElementRef<HTMLCanvasElement>;
canvasRef = viewChild<ElementRef<HTMLCanvasElement>>('canvasElement');
private ctx!: CanvasRenderingContext2D;
private settingsService = inject(SettingsService);
@@ -27,8 +27,8 @@ export class BrandAccent implements OnDestroy {
private bgGradient!: CanvasGradient;
private gridGradient!: CanvasGradient;
private offscreenCanvas!: OffscreenCanvas;
private offscreenCtx!: OffscreenCanvasRenderingContext2D;
private readonly offscreenCanvas!: OffscreenCanvas;
private readonly offscreenCtx!: OffscreenCanvasRenderingContext2D;
private resizeObserver?: ResizeObserver;
private intersectionObserver?: IntersectionObserver;
@@ -68,69 +68,69 @@ export class BrandAccent implements OnDestroy {
});
afterNextRender(() => {
this.ctx = this.canvasRef.nativeElement.getContext('2d', { colorSpace: 'srgb' })!;
const nativeElement = this.canvasRef()?.nativeElement;
this.ngZone.runOutsideAngular(() => {
this.resizeObserver = new ResizeObserver((entries) => {
for (let entry of entries) {
const { inlineSize: width, blockSize: height } = entry.borderBoxSize[0];
this.resize(width, height);
}
});
this.resizeObserver.observe(this.canvasRef.nativeElement);
if (nativeElement) {
this.ctx = nativeElement.getContext('2d', { colorSpace: 'srgb' })!;
this.intersectionObserver = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting) {
if (!this.animation.id) this.animate(performance.now());
} else if (this.animation.id) {
cancelAnimationFrame(this.animation.id);
this.animation.id = undefined;
this.ngZone.runOutsideAngular(() => {
this.resizeObserver = new ResizeObserver((entries) => {
for (let entry of entries) {
const { inlineSize: width, blockSize: height } = entry.borderBoxSize[0];
this.resize(width, height);
}
},
{ rootMargin: '200px' },
);
this.intersectionObserver.observe(this.canvasRef.nativeElement);
});
this.resizeObserver.observe(nativeElement);
// Safe Initialization
const rect = this.canvasRef.nativeElement.getBoundingClientRect();
this.resize(rect.width, rect.height);
this.intersectionObserver = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting) {
if (!this.animation.id) this.animate(performance.now());
} else if (this.animation.id) {
cancelAnimationFrame(this.animation.id);
this.animation.id = undefined;
}
},
{ rootMargin: '200px' },
);
this.intersectionObserver.observe(nativeElement);
this.animation.startTime = performance.now();
// Safe Initialization
const rect = nativeElement.getBoundingClientRect();
this.resize(rect.width, rect.height);
this.draw();
// this.animate(performance.now());
});
this.animation.startTime = performance.now();
this.draw();
// this.animate(performance.now());
});
}
});
}
private resize(width: number, height: number) {
const canvas = this.canvasRef.nativeElement;
const dpr = window.devicePixelRatio || 1;
const canvas = this.canvasRef()?.nativeElement;
if (canvas) {
const dpr = window.devicePixelRatio || 1;
this.rendererScale = dpr;
this.rendererScale = dpr;
canvas.width = width * dpr;
canvas.height = height * dpr;
canvas.width = width * dpr;
canvas.height = height * dpr;
if (this.offscreenCanvas) {
this.offscreenCanvas.width = width;
this.offscreenCanvas.height = height;
if (this.offscreenCanvas) {
this.offscreenCanvas.width = width;
this.offscreenCanvas.height = height;
}
this.canvasNativeSize = [width, height];
this.ctx.scale(dpr, dpr);
this.updateAnimationInfo();
this.animate(performance.now());
}
this.ctx.scale(dpr, dpr);
this.updateAnimationInfo();
this.update(performance.now());
this.draw();
}
private updateAnimationInfo() {
this.canvasNativeSize = [
this.canvasRef.nativeElement.clientWidth,
this.canvasRef.nativeElement.clientHeight,
];
this.animation.gridDimension = [
Math.trunc(this.canvasNativeSize[0] / 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) => {
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.draw();
};