-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4056996
commit a205f97
Showing
14 changed files
with
400 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,5 @@ | ||
<router-outlet /> | ||
<main class="size-full bg-white"> | ||
<app-background> | ||
<router-outlet /> | ||
</app-background> | ||
</main> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<section class="size-full relative"> | ||
<section | ||
#canvas_container | ||
class="size-full bg-black absolute top-0 left-0 right-0 bottom-0 after:block after:absolute after:top-0 after:left-0 after:right-0 after:bottom-0 after:size-full after:bg-[radial-gradient(circle,rgba(0,0,0,0)_50%,rgba(0,0,0,9)_75%,rgba(0,0,0,1)_100%)]" | ||
> | ||
<canvas | ||
#canvas | ||
class="size-full" | ||
></canvas> | ||
</section> | ||
|
||
<section class="size-full absolute z-10"> | ||
<ng-content></ng-content> | ||
</section> | ||
</section> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import { | ||
afterRender, | ||
ChangeDetectionStrategy, | ||
Component, | ||
HostListener, | ||
ViewChild, | ||
ViewEncapsulation, | ||
type ElementRef | ||
} from '@angular/core'; | ||
import type { Dimensions } from '../declarations/dimensions.interface'; | ||
import { BackgroundService } from './background.service'; | ||
|
||
@Component({ | ||
selector: 'app-background', | ||
standalone: true, | ||
imports: [], | ||
templateUrl: './background.component.html', | ||
encapsulation: ViewEncapsulation.None, | ||
changeDetection: ChangeDetectionStrategy.OnPush, | ||
viewProviders: [BackgroundService] | ||
}) | ||
export class BackgroundComponent { | ||
@ViewChild('canvas_container', { static: true }) | ||
public canvasContainerRef?: ElementRef<HTMLCanvasElement>; | ||
|
||
@ViewChild('canvas', { static: true }) | ||
public canvasRef?: ElementRef<HTMLCanvasElement>; | ||
|
||
private get desiredCanvasDimensions(): Dimensions { | ||
if (this.canvasContainerRef === undefined) { | ||
throw new Error('Canvas container element not found'); | ||
} | ||
|
||
return { | ||
widthPx: this.canvasContainerRef.nativeElement.clientWidth, | ||
heightPx: this.canvasContainerRef.nativeElement.clientHeight | ||
}; | ||
} | ||
|
||
constructor(private readonly backgroundService: BackgroundService) { | ||
afterRender(() => { | ||
if (this.canvasRef === undefined) { | ||
throw new Error('<canvas> is not found'); | ||
} | ||
|
||
this.backgroundService.attachCanvas(this.canvasRef.nativeElement); | ||
}); | ||
} | ||
|
||
@HostListener('window:resize') | ||
public onResize(): void { | ||
this.backgroundService.setContainerSize(this.desiredCanvasDimensions); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { Injectable, type OnDestroy } from '@angular/core'; | ||
import type { Dimensions } from '../declarations/dimensions.interface'; | ||
import { SceneContentManager } from './scene/scene-content-manager'; | ||
|
||
@Injectable() | ||
export class BackgroundService implements OnDestroy { | ||
private readonly sceneContentManager: SceneContentManager = new SceneContentManager(); | ||
|
||
public attachCanvas(canvas: HTMLCanvasElement): void { | ||
if (typeof window === 'undefined') { | ||
return; | ||
} | ||
this.sceneContentManager.initialize(canvas); | ||
} | ||
|
||
public setContainerSize(dimensions: Dimensions): void { | ||
this.sceneContentManager.setContainerSize(dimensions); | ||
} | ||
|
||
public ngOnDestroy(): void { | ||
this.sceneContentManager.destroy(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { Mesh, PlaneGeometry } from 'three'; | ||
import type { Dimensions } from '../../declarations/dimensions.interface'; | ||
import { GridMaterial } from './resourses/grid.material'; | ||
|
||
export class GridPlane extends Mesh<PlaneGeometry, GridMaterial> { | ||
constructor(dimensions: Dimensions) { | ||
const material: GridMaterial = new GridMaterial(dimensions); | ||
const geometry: PlaneGeometry = new PlaneGeometry(10, 10); | ||
super(geometry, material); | ||
this.rotation.x = -Math.PI / 3; | ||
this.translateZ(1); | ||
} | ||
|
||
public dispose(): void { | ||
this.removeFromParent(); | ||
this.geometry.dispose(); | ||
this.material.dispose(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import { type Camera, Color, type Scene, WebGLRenderer } from 'three'; | ||
import type { Dimensions } from '../../declarations/dimensions.interface'; | ||
|
||
class NotInitializedError extends Error { | ||
constructor() { | ||
super('WebGLRenderer is not initialized'); | ||
} | ||
} | ||
|
||
class NotDestroyedError extends Error { | ||
constructor() { | ||
super('WebGLRenderer is not destroyed'); | ||
} | ||
} | ||
|
||
export class RenderLoop { | ||
private webGLRenderer: WebGLRenderer | null = null; | ||
|
||
constructor( | ||
private readonly scene: Scene, | ||
private readonly camera: Camera | ||
) {} | ||
|
||
public initialize(canvas: HTMLCanvasElement): void { | ||
if (this.webGLRenderer !== null) { | ||
throw new NotDestroyedError(); | ||
} | ||
|
||
const webGLRenderer: WebGLRenderer = new WebGLRenderer({ | ||
canvas, | ||
antialias: true | ||
}); | ||
webGLRenderer.setClearColor(new Color(0x000000), 0); | ||
this.webGLRenderer = webGLRenderer; | ||
} | ||
|
||
public destroy(): void { | ||
if (this.webGLRenderer === null) { | ||
return; | ||
} | ||
|
||
this.webGLRenderer.dispose(); | ||
this.webGLRenderer = null; | ||
} | ||
|
||
public setDimensions({ widthPx, heightPx }: Dimensions): void { | ||
if (this.webGLRenderer === null) { | ||
throw new NotInitializedError(); | ||
} | ||
|
||
this.webGLRenderer.setSize(widthPx, heightPx); | ||
} | ||
|
||
public start(onRender?: (timeSinceLastFrameMs?: DOMHighResTimeStamp) => void): void { | ||
if (this.webGLRenderer === null) { | ||
throw new NotInitializedError(); | ||
} | ||
|
||
const webGLRenderer: WebGLRenderer = this.webGLRenderer; | ||
webGLRenderer.setAnimationLoop((timeSinceLastFrameMs: DOMHighResTimeStamp) => { | ||
webGLRenderer.render(this.scene, this.camera); | ||
|
||
if (typeof onRender !== 'function') { | ||
return; | ||
} | ||
onRender(timeSinceLastFrameMs); | ||
}); | ||
} | ||
|
||
public stop(): void { | ||
if (this.webGLRenderer === null) { | ||
throw new NotInitializedError(); | ||
} | ||
|
||
this.webGLRenderer.setAnimationLoop(null); | ||
} | ||
} |
Oops, something went wrong.