Framework entegrasyonları · Angular + Three
Host & Kök Sözleşmesi: Bileşenin Gümrük Masası
Angular'da WebGL sahnesi çoğu zaman bir
host bileşenin tuvalinde açılır. Bu sayfa
ElementRef / yaşam döngüsü / tek renderer sahipliği ile kök
sözleşmeyi anlatır: Angular CLI veya RxJS 101 değil · Three ↔ host kapısı.
Holodepth bu yaprağı «Angular nedir?» turu veya R3F
<Canvas> dersinin kopyası olarak yazmaz. R3F kök
mührü
Canvas & kök sözleşme
yaprağındadır; mercek orada React/Fiber, burada
bileşen host + DI ömrü. Mesh / buffer teorisi Three ve WebGL
omurgasındadır. Kare + NgZone
Kare döngüsü & NgZone
yaprağındadır. Dispose derinliği
Yükleme & OnDestroy
yaprağındadır. glTF şema format izleklerindedir.
Sayfayı bitirdiğinizde şu cümleyi kurabilmelisiniz: «Host bileşen tuvali gümrük masasıdır. Renderer AfterViewInit'te açılır, OnDestroy'da kapanır. ElementRef CSS kutusu ile backing store'u ayırır. Tek canlı context varsayılandır. SSR'de tarayıcı kapısı zorunludur. Sonraki kapı şablon → Object3D haritasıdır.»
Bu sayfanın sınırı · komşu konularla ayrım
Bu sayfa Angular + Three'de host kök sözleşmesini anlatır:
- Host bileşen / tuval sahipliği
AfterViewInitaçılış · boyut / DPR- Tek context · SSR / platform kapısı
- Üç host profili
Bilinçli olarak dışarıda bırakılan konular:
- R3F
Canvasprop yüzeyi → R3F · Canvas & kök - Şablon ↔ Object3D → Şablon → Object3D haritası
- NgZone / rAF → Kare döngüsü & NgZone
- Loader / OnDestroy dispose derinliği → Yükleme & OnDestroy
- Zone kaçışı / ada → Zone kaçışı & performans
- Angular temeli / DI 101 · FPS ms SLA → Platform · glTF/GLB → format izlekleri
Kısa ayrım: Bu sayfa «Angular host kapıyı nasıl mühürler?» · R3F Canvas «Fiber kapıyı nasıl mühürler?» · NgZone yaprağı «kapı açıkken tik nerede?» · Şablon haritası «kapının arkasında ağaç».
Gümrük masası: host bileşen
Imperatif demoda çoğu ekip index.html içine
<canvas> koyup script'te renderer açar. Angular
ürününde tuval bir component şablonuna aittir: stil, boyut, yaşam
döngüsü ve enjekte servisler bu masadan geçer. Holodepth: mesh'i yanlış
yazmak sahneyi bozar; host'u yanlış mühürlemek tüm oturumu bozar.
«angular-three» veya özel sarmalayıcı kütüphaneler bu masayı soyutlar; soyutlama yoksa da sözleşme aynıdır: kim canvas DOM'unu tutar, kim WebGLRenderer'ı yaratır, kim yok eder?
Şablon dekorasyonu taşımaz; host sözleşmeyi taşır.
AfterViewInit: kapı açılışı
Constructor veya ngOnInit içinde ViewChild canvas henüz
garanti değildir. Holodepth kök kuralı: renderer ve ilk
setSize tipik olarak AfterViewInit (veya
eşdeğeri view hazır sinyali) sonrasındadır. Erken erişim «null canvas»
veya 0×0 tampon üretir.
Kapanış: rota değişince bileşen ölür; GL kaynakları
ngOnDestroy hattına yazılır. Derin dispose / loader
sahipliği sonraki yapraktadır; burada mühür: açılış ve kapanış
aynı host ömrüne bağlıdır.
ElementRef: iki defter bağlantısı
CSS kutusu (layout) ile backing store (piksel tamponu) yine ayrıdır.
Host şablonunda width/height %100 ve min-height
yoksa R3F'deki «siyah kutu»nu Angular'da da yaşarsınız. Holodepth:
ViewChild ile canvas'ı alın; clientWidth/clientHeight ve
devicePixelRatio tavanıyla setSize /
setPixelRatio yazın.
| Defter | Angular yüzü | Kök kararı |
|---|---|---|
| Layout | Host CSS / flex / min-height | Tuval görünür alan |
| Backing store | setSize + DPR tavanı |
Fill-rate bütçesi |
| Yaşam | AfterViewInit ↔ OnDestroy | Context ömrü |
Resize: pencere veya yan panel açılınca host ölçüsü değişir.
ResizeObserver (veya bilinçli host dinleyicisi) setSize
yolunu tetikler. Her change detection'da setSize çağırmak thrashing
üretir; seyreltin.
Tek renderer · servis tuzağı
Her host kartında yeni WebGLRenderer = yeni context.
Dashboard'da üç küçük Angular bileşen üç GPU oturumu açabilir. Holodepth
varsayılanı: mümkün olduğunca tek canlı renderer; paylaşım
gerekiyorsa root-provided bir sahne servisi bilinçli tasarlanır, «her
child kendi Three'si» alışkanlığı yapılmaz.
Servis tuzağı: singleton renderer'ı yanlışlıkla ikinci kez oluşturmak veya destroy sonrası kullanmak. Sahiplik cümlesi ticket'ta: renderer host'ta mı, shared service'te mi?
SSR ve platform kapısı
Angular Universal / SSR ortamında window,
document ve WebGL yoktur. Holodepth: kök açılışı
isPlatformBrowser (veya eşdeğeri) arkasındadır. Sunucuda
renderer yaratmaya çalışmak build'i değil, runtime'ı kırar.
Hydration sonrası ilk frame: host boyutunun settle olmasını bekleyin; aksi 1×1 tampon riski. Bu Angular hydration dersi değil; Three host zamanlamasıdır.
Renderer imzası host'ta
Antialias, alpha, powerPreference, outputColorSpace, toneMapping ürün
sabitleri host açılışında bir kez mühürlenir. Her child'da rastgele
değiştirmek «neden renk kaydı?» tartışması üretir. R3F'de bu
gl / onCreated yüzüdür; Angular'da aynı diplomatik karar
host (veya shared factory) üzerindedir.
Kare metronom ve Zone politikası sonraki yapraktır. Burada yalnız: renderer varoluş sözleşmesi host ömrüne yazılır.
Güvenli host: simüle mühür
Örnekler öğretim amaçlı, güncel Angular + Three yüzeyine yaslanan simüle kalıplardır. CLI / standalone / NgModule ayrımı öğretilmez. Paket sürümlerinizi doğrulayın.
Simüle · vitrin hostu. Canvas ViewChild; açılış AfterViewInit; kapanış OnDestroy iskeleti.
import {
AfterViewInit, Component, ElementRef, OnDestroy, ViewChild,
} from '@angular/core'
import * as THREE from 'three'
@Component({
selector: 'app-stage-host',
template: `
<div class="stage-host" style="width:100%;height:100%;min-height:360px">
<canvas #glCanvas style="display:block;width:100%;height:100%"></canvas>
</div>
`,
// Eğitim: standalone / module seçimi ürün kararıdır.
})
export class StageHostComponent implements AfterViewInit, OnDestroy {
@ViewChild('glCanvas', { static: false })
private canvasRef!: ElementRef<HTMLCanvasElement>
private renderer?: THREE.WebGLRenderer
private resizeObs?: ResizeObserver
ngAfterViewInit(): void {
// SSR: burada isPlatformBrowser ile erken dönün (ürün kodunda).
const canvas = this.canvasRef.nativeElement
this.renderer = new THREE.WebGLRenderer({
canvas,
antialias: true,
alpha: false,
powerPreference: 'high-performance',
preserveDrawingBuffer: false,
})
this.renderer.outputColorSpace = THREE.SRGBColorSpace
this.renderer.toneMapping = THREE.ACESFilmicToneMapping
this.applySize()
this.resizeObs = new ResizeObserver(() => this.applySize())
this.resizeObs.observe(canvas.parentElement ?? canvas)
}
private applySize(): void {
const canvas = this.canvasRef?.nativeElement
const renderer = this.renderer
if (!canvas || !renderer) return
const w = canvas.clientWidth
const h = canvas.clientHeight
if (w < 2 || h < 2) return
const dpr = Math.min(window.devicePixelRatio || 1, 2)
renderer.setPixelRatio(dpr)
renderer.setSize(w, h, false)
}
ngOnDestroy(): void {
this.resizeObs?.disconnect()
this.renderer?.dispose()
this.renderer = undefined
// Scene/geometri dispose borusu Yükleme & OnDestroy yaprağında derinleşir.
}
}
Simüle · paylaşımlı kök notu. Birden fazla host kartı varsa ikinci renderer'ı varsayılan yapmayın; sahiplik cümlesi yazın.
/** @typedef {'host-local' | 'app-shared'} RendererOwnership */
/**
* Ürün ticket örneği — kod değil sözleşme.
* host-local → her StageHost kendi WebGLRenderer'ı (nadiren ≥2)
* app-shared → tek renderer; host'lar viewport / kamera dilimi paylaşır
*/
export const RENDERER_OWNERSHIP = /** @type {RendererOwnership} */ ('host-local')
export function assertSingleContext(liveRendererCount) {
if (RENDERER_OWNERSHIP === 'host-local' && liveRendererCount > 1) {
console.warn('[Holodepth] Birden fazla canlı context · mobil bütçeyi kontrol edin.')
}
}
Güvenlik: kullanıcıdan gelen canvas boyutlarını sınırsız şişirmeyin; DPR tavanı zorunlu. SSR'de native DOM API çağrılarını platform kapısı olmadan çalıştırmayın.
Change detection notu (eşik)
Her Angular CD turunda setSize / render çağırmak sessiz jank üreticisidir. Holodepth eşiği: kök montaj host'ta; sürekli tik Zone / rAF yaprağında; ağır kaçış Zone kaçışı yaprağında. Bu sayfa CD'yi öğretmez; host'un CD'ye bağlanmaması gerektiğini mühürler.
Üç host profili
-
01 · Host
Ürün vitrini
- Sahiplik
- host-local renderer
- DPR
- Tavan 2 · keskinlik
- Risk
- İkinci kartta ikinci context
-
02 · Host
Dashboard paneli
- Sahiplik
- app-shared adayı
- Boyut
- Sabit min-height · ResizeObserver
- Risk
- Her widget kendi GL
-
03 · Host
SSR + client hydrate
- Kapı
- isPlatformBrowser
- Açılış
- AfterViewInit + settle
- Risk
- Sunucuda WebGL denemesi
Host tuzakları
- Erken ViewChild: ngOnInit'te canvas null.
- 0 yükseklik: flex child min-height yok.
- Çoklu context: kart başı renderer.
- SSR çağrısı: platform kapısız WebGL.
- CD thrash: her turda setSize.
- Destroy yok: rota sonrası context sızıntısı.
- R3F ezberi: frameloop prop'u aramak.
Holodepth perspektifleri
Ömür = context
Renderer host ömrüne yazılır. Orphan context mobilin sessiz düşmanıdır.
Bir context varsayılan
İkinci host ikinci gerekçe ister; kart ızgarası gerekçe değildir.
İki defteri ayırın
CSS kutusu ile DPR tamponu aynı satırda konuşulmamalı.
Teşhis maddeleri
- Renderer AfterViewInit'te mi açılıyor?
- Host min-height / boyut sözleşmesi var mı?
- DPR tavanı yazılı mı?
- Canlı context sayısı gerekçeli mi?
- SSR platform kapısı var mı?
- ResizeObserver thrash yapıyor mu?
- ngOnDestroy renderer'ı salıyor mu?
- R3F veya glTF şema bu sayfaya sızmış mı?
Holodepth içgörüsü
«Angular'da Three çalışmıyor» çoğu zaman mesh hatası değil; host zamanlaması, sıfır kutu veya çoklu context sorunudur. Önce gümrük masasını okuyun.
Sonraki kapı: şablon haritası
Kapı mühürlendikten sonra Angular şablonu (veya kütüphane yapı taşları) Object3D ağacına nasıl bağlanır? Sonraki sayfa Şablon → Object3D haritası bu eşlemeyi anlatır. NgZone döngüsü ve OnDestroy derinliği sonraki yapraklardadır.