holodepth

Framework entegrasyonları · Angular + Three

Şablon → Object3D Haritası: İki Ağacın Diplomasisi

Angular görünüm ağacı ile Three Object3D ağacı aynı şey değildir. Bu sayfa şablon / bileşen girdilerinin sahne grafına nasıl bağlandığını anlatır: HTML semantiği değil · Three ↔ Angular eşleme.

Holodepth bu yaprağı Angular template sözdizimi dersi veya R3F JSX katalog turunun kopyası olarak yazmaz. R3F haritası Deklaratif sahne grafı yaprağındadır (JSX intrinsikleri). Host kapısı Host & kök sözleşmesi yaprağındadır. Object3D matematik teorisi Three omurgasındadır. NgZone karesi sonraki Angular yaprağındadır. glTF node spekü format izleklerindedir.

Sayfayı bitirdiğinizde şu cümleyi kurabilmelisiniz: «Angular view ile Object3D iki ayrı ağaçtır. @Input sahne alanına bilinçli yazılır. @for kimliği remount üretebilir. İç içe host bileşenleri group diplomasisidir. Şablonda görünmez etmek ile grafıtan düşürmek farklıdır. Sonraki kapı kare döngüsü & NgZone'dur.»

Bu sayfanın sınırı · komşu konularla ayrım

Bu sayfa Angular + Three'de şablon → Object3D haritasını anlatır:

  • İki ağaç diplomasisi · input → alan yazımı
  • Liste kimliği / remount · iç içe bileşen = group
  • visible vs remove · kütüphane yapı taşı sınırı
  • Üç yazım profili

Bilinçli olarak dışarıda bırakılan konular:

Kısa ayrım: Bu sayfa «şablon sahneye nasıl map olur?» · R3F deklaratif «JSX kataloğa nasıl map olur?» · Host «kapı nerede?» · NgZone «map sonrası kim her kare iter?».

İki ağaç: view ve Object3D

Angular, bileşen/şablon ağacını change detection ile yaşatır. Three, Scene altındaki Object3D parent zincirini render eder. Holodepth: şablonda «iç içe yazmak» otomatik parent zinciri demek değildir; siz (veya kütüphane) add / group bileşeni ile bağı kurarsınız.

R3F bu bağı reconciler ile gizler. Angular + Three'de bağ çoğu zaman açık veya ince sarmalayıcıdır. «Çalıştı» ile «hangi ağaçta yaşadı?» sorusunu ayırın.

Aynı ekranda iki soyağacı; karıştırmak yetim mesh üretir.

Üç yazım stili

Holodepth pratikte üç stil görür (ürün birini seçer):

  1. Servis merkezli: şablon yalnız canvas host; tüm Object3D TypeScript'te kurulur.
  2. Bileşen merkezli: her parça bir Angular component; ngOnInit/view hazır olunca kendini scene'e ekler.
  3. Kütüphane kataloglu: angular-three benzeri yapı taşları şablonda yer alır; altta yine Object3D üretilir.

Bu sayfa stilleri yarıştırmaz; harita disiplininin üçünde de geçerli olduğunu mühürler: kim parent, kim input yazar, kim destroy'da çıkar.

@Input → sahne alanı

Angular @Input() (veya input signal) DOM attribute'u değildir; ürünün Object3D alanına köprüdür: position, visible, renk, yoğunluk. Holodepth: input değişimini her CD'de körce yeni Vector3 allocate etmek GC üretir; mevcut nesneye set edin veya seyrek güncelleyin.

Girdi kapıları · Angular yüzü
Girdi Sahne etkisi Tuzak
Konum / dönüş position.set / quaternion Her CD yeni dizi → gürültü
Görünürlük visible bayrağı Hâlâ raycast / maliyet taşıyabilir
Varlık kapısı @if ile bileşeni yok et Dispose unutulursa sızıntı

R3F'deki args/attach üçlüsü JSX katalog dilidir. Angular'da eşdeğer soru: kurucu parametresi component input mu, yoksa serviste sabit mi?

İç içe bileşen = group diplomasi

Şablonda <app-assembly><app-part/></app-assembly> yazmak, content projection ile çocukları DOM'a yerleştirir. Object3D tarafında çocuk mesh'in parent'ı assembly group olmalı; aksi hâlde dünya uzayında «kardeş gibi» uçuşurlar. Holodepth: montaj bileşeni kendi THREE.Group'unu yaratır; çocuklar bu group'a add eder (veya kütüphane bunu yapar).

Projection (ng-content) view ağacını düzenler; sahne parent'ını otomatik vermez. İki ağaç diplomasisini burada unutmayın.

@for kimliği ve remount

@for (item of items; track item.id) Angular view kimliğidir. Track bozulursa bileşen yeniden doğar; Object3D de çoğu kalıpta yeniden yaratılır → flicker, state kaybı, dispose yükü. Holodepth: track'i ürün kimliğine bağlayın; index track'i kalabalıkta pahalıdır.

Binlerce benzer öğe için şablon döngüsü yerine instance kaçışı (Zone / performans yaprağı ve Three instancing) düşünülür. Bu sayfa eşik sinyalini koyar, matematiği açmaz.

Gizle ≠ grafıtan çıkar

visible = false çizimi kesebilir ama nesneyi grafta tutar. @if (show) ile bileşeni yok etmek grafıtan düşürme + yaşam sonu demektir. Holodepth ürün cümlesi: geçici gizleme mi, ömür sonu mu? Ikisini karıştırmak hem picking hem bellek sürprizi üretir.

Şablon yalan söyleyebilir; Object3D hâlâ oradadır.

CD'den sahneye itiş

Input değişince Object3D'yi güncellemek doğrudur; her CD turunda tüm sahneyi yeniden kurmak değildir. Holodepth: kurulum bir kez (view hazır), güncelleme diff ile. Sürekli itiş ve Zone maliyeti sonraki yaprakta derinleşir; burada yalnız «map ≠ her tur rebuild» kuralı mühürlenir.

Kütüphane yapı taşı sınırı

angular-three ve benzerleri R3F'ye yakın şablon katalogları sunabilir. Holodepth: yapı taşını ezber demeti saymayın; altında yine Object3D ve parent kuralı vardır. Katalog API'si değişebilir; iki ağaç diplomasisi kalır. Host sözleşmesini kütüphaneye tamamen teslim etmek teşhisi zorlaştırır.

Güvenli harita: simüle bağ

Örnekler öğretim amaçlıdır. Angular CLI / signal API varyantları öğretilmez. Host'ta bir Scene olduğu varsayılır.

Simüle · parça bileşeni group'a kendini ekler.

import {
  Component, Input, OnChanges, OnDestroy, SimpleChanges,
} from '@angular/core'
import * as THREE from 'three'

@Component({
  selector: 'app-part-node',
  template: '', // Görünür DOM yok · yalnızca Object3D üretir
})
export class PartNodeComponent implements OnChanges, OnDestroy {
  /** Ebeveyn Object3D (montaj group). Host / parent sağlar. */
  @Input({ required: true }) parent!: THREE.Object3D
  @Input() offset: [number, number, number] = [0, 0, 0]
  @Input() selected = false

  private mesh?: THREE.Mesh
  private readonly mat = new THREE.MeshStandardMaterial({
    color: '#9aa6b8', metalness: 0.2, roughness: 0.45,
  })

  ngOnChanges(changes: SimpleChanges): void {
    if (!this.parent) return
    if (!this.mesh) {
      this.mesh = new THREE.Mesh(new THREE.BoxGeometry(1, 0.35, 0.6), this.mat)
      this.mesh.name = 'part-node'
      this.parent.add(this.mesh)
    }
    if (changes['offset'] && this.mesh) {
      const [x, y, z] = this.offset
      this.mesh.position.set(x, y, z)
    }
    if (changes['selected']) {
      this.mat.color.set(this.selected ? '#5ec8ff' : '#9aa6b8')
    }
  }

  ngOnDestroy(): void {
    if (!this.mesh) return
    this.parent?.remove(this.mesh)
    this.mesh.geometry.dispose()
    // Materyal paylaşımı varsa dispose politikası OnDestroy yaprağında.
    this.mat.dispose()
    this.mesh = undefined
  }
}

Simüle · montaj group + şablon yerleştirme notu.

import { Component, Input, OnDestroy, OnInit } from '@angular/core'
import * as THREE from 'three'

/**
 * Template örneği (ayrı dosyada):
 *   @for (p of parts; track p.id) {
 *     <app-part-node [parent]="group" [offset]="p.offset" [selected]="p.id === selectedId" />
 *   }
 * track = ürün kimliği · index track kullanmayın.
 */
@Component({
  selector: 'app-assembly',
  templateUrl: './assembly.component.html',
})
export class AssemblyComponent implements OnInit, OnDestroy {
  @Input({ required: true }) scene!: THREE.Scene
  @Input() parts: { id: string; offset: [number, number, number] }[] = []
  @Input() selectedId: string | null = null

  /** Çocukların parent'ı · şablon [parent]="group" ile beslenir */
  readonly group = new THREE.Group()

  ngOnInit(): void {
    this.group.name = 'assembly'
    this.scene.add(this.group)
  }

  ngOnDestroy(): void {
    this.scene.remove(this.group)
    // Çocuk part'lar kendi ngOnDestroy ile çıkar.
  }
}

Güvenlik: kullanıcı string'ini mesh.name / eval yolu yapmayın. Offset dizilerini doğrulamadan GPU'ya yazmayın. @for listesini kimliği belirsiz stringlerden üretmeyin.

Harita tuzakları

  1. DOM hiyerarşisi = parent sanmak: add unutulur.
  2. Her CD'de new Mesh: mezarlık.
  3. track index: yanlış remount.
  4. visible ile @if karışımı: tutarsız ömür.
  5. Paylaşılan materyal dispose: komşu ölür.
  6. Projection = otomatik group: yanılgı.
  7. R3F attach ezberi: Angular'da aynı API yok.

Üç harita profili

  • 01 · Harita

    Servis merkezli

    Şablon
    Yalnız host canvas
    Ağaç
    TS'te Scene kurumu
    Risk
    God-service şişmesi
  • 02 · Harita

    Parça bileşenleri

    Şablon
    @for + app-part-node
    Parent
    Group input zorunlu
    Risk
    track / remount
  • 03 · Harita

    Katalog kütüphane

    Şablon
    Yapı taşı etiketleri
    Disiplin
    İki ağacı yine bilin
    Risk
    Sihir sanmak

Holodepth perspektifleri

İki ağacı ayrı konuşun

View hiyerarşisi ile Object3D parent aynı cümlede varsayılmamalı.

Kur bir kez, güncelle diff ile

Her CD rebuild, Angular Three'nin klasik tuzaklarındandır.

track = ürün kimliği

Index track kalabalıkta pahalı ve yanıltıcıdır.

Teşhis maddeleri

  1. Parent Object3D bilinçli mi veriliyor?
  2. Input değişimi allocate mi, set mi?
  3. @for track ürün kimliği mi?
  4. visible vs @if politikası net mi?
  5. Projection sahne parent'ı sanılmış mı?
  6. Kurulum CD yağmuruna mı bağlanmış?
  7. Kütüphane soyutlaması teşhisi engelliyor mu?
  8. R3F attach veya glTF şema bu sayfaya sızmış mı?

Holodepth içgörüsü

«Şablonda yazdım ama sahnede yok» çoğu zaman CSS değil, iki ağaç diplomasisinin kopukluğudur. Önce parent'ı sorun, sonra input'u.

Sonraki kapı: kare & NgZone

Harita durağanı anlatır; canlı ürün her karede mutasyon ister. Sonraki sayfa Kare döngüsü & NgZone tik ile Zone vergisini anlatır. Yükleme / picking / kaçış sonraki yapraklardadır.