IFC Viewer SDK v1.18.0 Apri il viewer
Italiano

IFC Viewer SDK · v1.18.0

Integra il viewer IFC nel tuo prodotto

Inserisci lo stesso viewer del browser nel tuo CDE, digital twin o strumenti interni di progetto. Carica dati IFC dalla tua app mentre ogni modello viene analizzato nel client.

Tre righe fino al primo render

JavaScript
const viewer = new IfcViewer("#viewer");

await viewer.add("project.ifc", ifcBytes);
// → rendered, validated, all on the client

Configurazione

Avvio rapido

Scegli il tuo stack. Copia, incolla, renderizza — senza build, senza chiave API.

HTML
<div id="viewer" style="height:520px"></div>
<script type="module">
  import { IfcViewer } from "https://www.ifcvieweronline.eu/sdk/ifc-viewer.es.js";

  const viewer = new IfcViewer("#viewer");

  // Load IFC bytes from your app — nothing is uploaded
  const bytes = await fetch("/models/project.ifc").then(r => r.arrayBuffer());
  await viewer.add("project.ifc", bytes);
</script>

Ospitato da noi o da te

Gli snippet importano dalla nostra CDN, che funziona su qualsiasi origine. Per ospitarlo tu, servi ifc-viewer.es.js dal tuo dominio — l’SDK ricava l’URL dell’app relativamente allo script. L’app è altrove? Usa l’opzione baseUrl.

Non c’è ancora un pacchetto npm: importa il modulo via URL (sopra) oppure includi ifc-viewer.es.js nella tua app.

Dimostrazione

Demo live

Questa pagina sta eseguendo il SDK. Clicca un controllo per scaricare un IFC di esempio e guidare il viewer — ogni pulsante mostra la chiamata che effettua.

inattivo
Ultima chiamata —

Architettura

Come funziona

Un wrapper minimo nella tua pagina, il viewer completo in un iframe isolato, i tuoi byte trasferiti tra i due — ed elaborati dove già si trovano.

Browser del visitatore — non viene caricato nullaLa tua appSDK · ~6 KBiframe isolatothree.js · web-ifc · WASMByte IFCpostMessage

La tua app

Un modulo ES da ~6 KB che crea un iframe e un’API JS tipizzata. Nulla del peso 3D o del parsing finisce nel tuo bundle.

Ponte postMessage

I byte IFC vengono trasferiti all’iframe come ArrayBuffer (senza copia). Comandi e query sono messaggi correlati di richiesta/risposta.

Il viewer

three.js + web-ifc compilato in WebAssembly effettuano il parsing e il rendering del modello dentro l’iframe — sulla macchina del visitatore.

Perché è privato

I modelli non raggiungono mai un server. Nessuna pipeline di upload da proteggere, nessuna questione di residenza dei dati, nessuna coda per dimensione del file.

Perché scala

Il calcolo gira sul dispositivo di ogni visitatore. Servire un modello da 200 MB costa quanto uno da 2 MB — è un file statico.

Concetti

Concetti chiave

Quattro cose da sapere prima di costruire.

Montaggio e prontezza

new IfcViewer(target) monta subito e mette in coda i comandi finché il viewer non è pronto. await IfcViewer.create(target) (o whenReady()) restituisce un’istanza utilizzabile immediatamente.

JavaScript
// queues commands until ready
const viewer = new IfcViewer("#viewer");

// …or await an instance that is ready to use
const viewer = await IfcViewer.create("#viewer");

Byte o URL

add(name, bytes) trasmette byte che hai già — niente CORS, niente caricato; il buffer viene trasferito (resta detached), quindi passa una copia se ti serve ancora. addFromUrl(url) scarica invece un URL pubblico con CORS abilitato.

JavaScript
// you already have the bytes — no CORS, nothing uploaded
await viewer.add("a.ifc", bytes);

// …or load a public, CORS-enabled URL
await viewer.addFromUrl("https://host/b.ifc");

Eventi

Iscriviti con on(event, cb), che restituisce una funzione per annullare l’iscrizione. Hai ready, model-progress, model-loaded, validation-completed, model-error ed element-selected.

JavaScript
const off = viewer.on("model-loaded", (m) => {
  console.log(m.fileName, m.elementCount);
});
// later: off();

Query

Estrai dati su richiesta: getModels, getElement, getValidation, getStats, getIssues, checkIds, checkEir, screenshot. Ognuna è richiesta/risposta e viene rifiutata dopo un timeout (30 s; IDS / EIR fino a 120 s).

JavaScript
const models = await viewer.getModels();
const { qualityScore } = await viewer.getValidation();
const png = await viewer.screenshot();

Riferimento

Riferimento API

Tutti i metodi, raggruppati — con firme e tipi di ritorno. Seguono le opzioni del costruttore, gli eventi e il web component <ifc-viewer>.

Costruttore

new IfcViewer(target, options?)IfcViewer

Monta in un selettore CSS o elemento. Vedi le opzioni qui sotto.

IfcViewer.create(target, options?)Promise<IfcViewer>

Crea un viewer e si risolve non appena è pronto ad accettare comandi.

Caricamento dei modelli

add(name, bytes)Promise<ModelLoadedEvent>

Carica byte IFC (ArrayBuffer/Uint8Array) dalla tua app. Il buffer viene trasferito per un passaggio senza copia.

addFromUrl(url, name?)Promise<ModelLoadedEvent>

Carica un URL IFC pubblico con CORS.

removeModel(modelId)void

Scarica un modello per id.

clear()void

Rimuovi tutti i modelli caricati.

Camera e selezione

select(expressId | globalId, modelId?)void

Seleziona e inquadra un elemento — per expressID IFC o per GlobalId (che trova anche il suo modello).

setView(view)void

Vola a una vista con nome della scena — iso, front, back, left, right, top, bottom — con tutta la scena inquadrata. Senza risposta (tra 1.14 e 1.17 il viewer la ignorava).

frame({ view?, fill?, azimuth?, elevation?, animate? })Promise<{ scope }>

Inquadratura per la presentazione: il modello occupa `fill` del riquadro (0,2–0,98, predefinito 0,85), adattato ai suoi spigoli e non alla sfera che lo contiene. azimuth / elevation scelgono l’angolo.

frame(elementId, modelId?, options?)Promise<{ scope: 'element' }>

Inquadra un elemento (expressID): dall’angolazione attuale salvo che sia indicata una vista. Rifiuta se non è nel modello.

fit() · reset()void

Inquadra il modello attivo dall’angolazione attuale, con margine / reimposta la camera.

setCamera(position, direction)void

Posiziona la camera in una posizione guardando in una direzione.

getCamera()Promise<CameraState | null>

Dove si trova la camera e cosa guarda — salvalo e ripristinalo con lookAt.

lookAt(position, target, animate?)Promise<void>

Porta la camera in una posizione guardando un obiettivo (metri di scena, Y in alto).

setWalkMode(enabled, { speed? })Promise<WalkState>

Modalità passeggiata in prima persona (WASD, trascina per guardare, Esc per uscire). Emette walk-changed.

getWalkState()Promise<WalkState>

Se la modalità passeggiata è attiva e a che velocità.

Visibilità

isolate(ifcType?)void

Isola una categoria (es. "IfcWall"); ometti per azzerare.

showAll()void

Ripristina la piena visibilità (rimuovi nascosti + isolamento).

hideElements(ids, modelId?) · showElements(ids, modelId?)void

Nasconde / mostra un insieme di elementi per expressID.

setModelVisible(modelId, visible)Promise<void>

Mostra o nasconde un modello di una scena federata senza scaricarlo.

setModelOpacity(opacity, modelId?)Promise<void>

Rende traslucido un modello (0,05–1) — ad es. l’architettura attorno agli impianti.

isolateModel(modelId | null)Promise<void>

Mostra solo questo modello; null li mostra di nuovo tutti.

Aspetto e presentazione

setBackground(background)Promise<BackgroundState>

Cambia lo sfondo della scena: un preset ('white', 'paper', 'blueprint', 'sky', 'studio'), '#rrggbb', '#alto,#basso' o { top, bottom }. Non salvato come preferenza del visitatore.

getBackground()Promise<BackgroundState>

Lo sfondo attuale della scena.

setAccent(color)Promise<void>

Cambia il colore d'accento dell'interfaccia a runtime (#rrggbb).

setClientMode(enabled)Promise<void>

Attiva o disattiva la vista cliente — quella per gli stakeholder, come ui: 'client'.

setRenderQuality(quality)Promise<void>

'quality' attiva il rendering più pesante per un'immagine di copertina; 'standard' per tutti i giorni.

Studio solare

setSolar(opts?)Promise<SolarState>

Ombre reali a una data e ora locali del sito: { date: '06-21', time: '18:00' }. Il sito viene dalla georeferenziazione IFC; passa location per un modello senza — mai una città predefinita in silenzio.

getSolar()Promise<SolarState>

Data, ora e fuso dello studio, e dove si trova il sito.

Modalità mappa

setSiteContext(opts?)Promise<SiteContextState>

Colloca il modello sulla mappa con terreno e dintorni OpenStreetMap. Chiamarlo significa che la tua pagina dichiara il consenso alle tessere per i suoi visitatori; mostra le attribuzioni.

getSiteContext()Promise<SiteContextState>

Stato della modalità mappa, il posizionamento e le attribuzioni da mostrare.

Scene

openScene(url | SceneDocument)Promise<void>

Aprire un’altra scena: l’URL di un .scene.json o un documento di scena (viaggia compresso nell’indirizzo del frame, quindi deve stare in un link). Il visualizzatore si ricarica; le chiamate in attesa vengono rifiutate e ready scatta di nuovo.

exportScene({ title?, description?, camera? })Promise<SceneExport>

La scena a schermo come documento di scena — modelli per URL, livelli, gemello, mappa, camera — con le fonti da citare e un link che la contiene.

packScene(doc)Promise<string | null>

Comprimere da sé un documento di scena per un link #scene= (null se è troppo grande per un link).

Livelli di dati e gemello

getLayerPresets()Promise<LayerPreset[]>

Il catalogo delle fonti pubbliche in tempo reale, con nome nella lingua del visualizzatore, ciò che serve a ciascuna in un browser (una chiave, un proxy) e se ha dati vicino al sito.

addLayer({ preset } | { url, live? } | { geojson })Promise<DataLayerInfo>

Aggiungere un livello: una fonte del catalogo ({ preset }), GeoJSON o un feed in tempo reale a un URL ({ url, live }), o GeoJSON che hai già ({ geojson }). Solo per la sessione: mai salvato nei livelli del visitatore.

getLayers()Promise<DataLayerInfo[]>

Tutti i livelli di dati: stato, numero di elementi, estensione, aggiornamento e attribuzione.

setLayerVisible(id, visible)Promise<DataLayerInfo>

Mostrare o nascondere un livello.

frameLayer(id)Promise<void>

Portare la camera sugli elementi di un livello.

removeLayer(id)Promise<void>

Rimuovere un livello.

getTwin()Promise<TwinState>

Il gemello operativo adesso: fonti dei dispositivi (stato, ultima lettura) e, per collegamento, la regola soddisfatta, il suo colore, il valore dell’etichetta e se è in allarme.

Sezioni

addSection({ axis?, offset?, level?, flip? })Promise<SectionsState & { id }>

Aggiunge un piano di sezione. { level: 'Piano 1' } è una pianta a quel livello; { axis: 'x', offset: 4.5 } una sezione a 4,5 m.

updateSection(id, { offset?, enabled?, flipped? })Promise<SectionsState>

Sposta, attiva/disattiva o inverte un piano.

removeSection(id?)Promise<SectionsState>

Rimuove un piano, o tutti i tagli senza id.

setSectionBox('model' | 'selection' | false)Promise<SectionsState>

Un box di sezione attorno al modello o alla selezione; false lo rimuove.

getSections()Promise<SectionsState>

Tutti i piani, il box e i livelli disponibili per i tagli per piano.

Tour

startTour(template?, { autoplay?, title? })Promise<TourState>

Avvia un tour predefinito: 'social', 'client-walkthrough' o 'technical-review' (percorre le anomalie di validazione). Riprodotto dalla barra tour del viewer.

playTour({ title?, steps }, { startAt?, autoplay? })Promise<TourState>

Riproduce un tour creato da te: soste della camera con didascalie, evidenziazioni e classi isolate. autoplay: true o ms per sosta.

nextTourStep() · prevTourStep() · goToTourStep(i)Promise<TourState>

Passare da una sosta all’altra.

setTourAutoplay(autoplay)Promise<TourState>

Attiva o disattiva l’avanzamento automatico del tour in corso.

stopTour()Promise<TourState>

Ferma il tour e restituisce la camera.

getTour()Promise<TourState>

Il tour e le sue soste, nel formato di playTour() — salvalo e riproducilo più tardi.

Regista di presentazioni

getPresentationRecipes()Promise<PresentationRecipe[]>

Le ricette integrate del regista (demo per riunione, reel, teaser LinkedIn, lancio, look editoriali…).

createPresentation(recipe?, options?)Promise<PresentationState>

Trasforma il modello in un video montato da una ricetta: inquadrature pianificate dall’IFC, didascalie, musica. Apre Clip Studio con il risultato. Segui presentation-progress.

exportPresentation({ resolution?, music? })Promise<PresentationVideo>

Codifica la presentazione nel browser del visitatore e restituisce i byte dell’MP4 — da caricare, allegare o riprodurre in un <video>.

closePresentation()Promise<void>

Chiude Clip Studio.

Studio copertine

getCoverOptions()Promise<CoverCatalog>

Le ricette, i modelli, i formati e le palette dello studio copertine.

createCover({ recipe?, template?, format?, palette?, text? })Promise<CoverState>

Crea una copertina: esegue una ricetta (cattura le viste necessarie), poi imposta modello, formato, palette e testi. Apre lo studio, ancora modificabile.

getCover()Promise<CoverState | null>

La copertina così com’è, o null se lo studio è chiuso.

exportCover({ type?, slide? })Promise<CoverFile>

Esportala: png / jpeg (una pagina), pdf / pptx (tutto il documento), zip (tutte le pagine). Restituisce i byte.

closeCover()Promise<void>

Chiude lo studio copertine.

Kit articolo

activate()void

Avvia subito un visualizzatore differito (ciò che fa il pulsante del poster). Le chiamate precedenti erano in coda.

bindSteps(steps, { rootMargin? })() => void

Scrollytelling: mentre ogni paragrafo attraversa il centro dello schermo, inquadra, isola, muove il sole o esegue il tuo codice. Restituisce una funzione per sganciare.

setTurntable(enabled | degPerSec)Promise<{ active, speed }>

Una lenta rotazione a riposo (gradi al secondo; false la ferma). Si ferma al primo tocco, mai con movimento ridotto.

toggleFullscreen()Promise<void>

Porta la figura a schermo intero, o torna indietro.

setPaused(paused)Promise<{ paused }>

Sospende o riprende il rendering. pauseOffscreen lo fa per te.

Gruppi di scena

getGroups()Promise<SceneGroupsState>

Tutti i gruppi della scena — dedotti dall’IFC (progetto, sito, posizione) e creati dagli utenti.

createGroup(name, modelIds?)Promise<string>

Crea un gruppo, eventualmente con modelli. Restituisce il suo id.

renameGroup(id, name) · deleteGroup(id)Promise<void>

Rinomina o elimina un gruppo utente. I gruppi automatici non si modificano.

assignToGroup(itemId, groupId | null | 'loose')Promise<void>

Sposta un modello o una nuvola di punti in un gruppo; null lo restituisce al raggruppamento automatico, 'loose' lo lascia senza gruppo.

setGroupVisible(id, visible) · isolateGroup(id | null)Promise<void>

Mostra o nasconde un intero gruppo, o ne mostra solo uno.

frameGroup(id)Promise<void>

Inquadra la camera su un gruppo, membri nascosti inclusi.

Misure

setMeasureTool(tool)Promise<void>

Arma uno strumento di misura per il visitatore (apre il pannello Misura), o 'none'. I risultati arrivano su measurements-changed.

getMeasurements()Promise<MeasurementsState>

Tutte le misure sullo schermo. Valori in SI — metri, m², gradi — qualunque cosa mostri il viewer.

clearMeasurements(id?)Promise<MeasurementsState>

Rimuove una misura, o tutte.

Query

getModels()Promise<ModelSummary[]>

Elenca i modelli caricati. Restituisce una promise.

findElements({ ifcClass?, globalId?, name?, modelId?, limit? })Promise<ElementSummary[]>

Trova elementi per classe IFC, GlobalId e/o nome nei modelli caricati. Ogni risultato ha ciò che chiedono getElement(), select() e frame().

getElement(expressId | globalId, modelId?)Promise<IfcElementData | null>

Per expressID o GlobalId. I dati IFC di un elemento: attributi con il GlobalId, i suoi set di proprietà e quantità, e quelli del suo tipo — typeName, typeProperties — con unità. effectivePropertySets li unisce e vince il valore proprio dell’elemento.

validate(modelId?, { force? })Promise<ValidationRunResult>

Valida un modello adesso (di default, quello attivo) e risolve con il suo Health Score e il conteggio dei problemi. Rifiuta con il motivo.

getValidation()Promise<ValidationSummary | null>

Il risultato di validazione a schermo, o null prima che un’esecuzione ne abbia prodotto uno. Vedi «Ciclo della validazione».

getValidationStatus()Promise<ValidationStatus>

A che punto è la validazione: idle, running (con avanzamento), done o error.

getStats()Promise<StatsResult>

Conteggio elementi per categoria e modello — per i grafici. Restituisce una promise.

getIssues({ severity?, limit?, modelId? })Promise<IssuesResult>

Problemi di validazione per una tabella (filtra per gravità / limite). Restituisce una promise.

screenshot()Promise<string>

Cattura la vista 3D corrente come data URL PNG. Restituisce una promise.

compare({ base, head, baseLabel?, headLabel? })Promise<{ changes }>

Confronta due consegne per URL (per GlobalId) e apre l’area di confronto sul risultato.

Pannelli

openPanel(panel | null) · closePanel()void

Apre un pannello strumento, oppure null per chiudere quello aperto. Un pannello non disponibile — nascosto dal chrome, o senza nulla di caricato su cui agire — non fa nulla, e non è un errore.

getPanels()Promise<PanelsResult>

Quale pannello è aperto e quali sono offerti in questo momento. Uno strumento assente da `available` non può essere aperto; non è semplicemente disabilitato.

setPanels(panels)void

Limita la barra a questi pannelli, a runtime. Stesso vocabolario del parametro URL `panels=` e ha la precedenza su di esso. Restringe ciò che il viewer offre e non aggiunge mai; un array vuoto significa nessuna barra.

Nuvole di punti

addPointCloud(fileName, bytes)Promise<string>

Carica una scansione da byte — LAS, LAZ, COPC, PLY, PCD o testo. Il buffer viene trasferito, non copiato. Restituisce l'id della nuvola.

addPointCloudFromUrl(url, fileName?)Promise<string>

Carica una scansione che il visualizzatore scarica da sé. L'URL deve consentire CORS.

listPointClouds()Promise<PointCloudInfo[]>

Tutte le scansioni caricate. `pointCount` è ciò che risiede in memoria, `declaredCount` ciò che contiene il file — differiscono quando il budget ha troncato la lettura.

removePointCloud(cloudId) · clearPointClouds()Promise<void>

Scarica una scansione e libera i suoi buffer GPU, oppure scaricale tutte.

setPointCloudVisible(cloudId, visible)Promise<void>

Mostra o nasconde una scansione senza scaricarla.

fitPointCloud(cloudId?)Promise<void>

Inquadra la camera su una scansione, o sulla prima caricata.

setPointCloudDisplay(display, renderBudget?)Promise<void>

Dimensione dei punti, opacità, modalità colore, densità, soglia di confidenza — condivisi da tutte. Ognuno è un uniform dello shader, quindi immediato su 20 milioni di punti.

inspectPointCloud(enabled?)Promise<void>

Arma il clic per leggere. Da armato, cliccare un punto emette `pointcloud-picked` con le coordinate DEL FILE accanto a quelle della scena.

setPointCloudPlacement(placement, cloudId?)Promise<void>

Regola una scansione a mano: posizione, imbardata, livellamento, scala. Parziale e limitato; si applica sopra l'allineamento dedotto senza sostituirlo.

setPointCloudUpAxis(axis, cloudId?)Promise<void>

Corregge quale asse la scansione considera verticale. PLY, PCD e testo non dichiarano orientamento, il visualizzatore lo deduce — controlla `upAxisSource`.

Imported 3D models

addMesh(files)Promise<string>

Importa un modello da byte. Richiede un ELENCO: un .gltf ha bisogno del suo .bin e delle texture, un .obj del suo .mtl — da solo, il file di ingresso dà geometria grigia.

addMeshFromUrl(urls)Promise<string>

Importa un modello che il visualizzatore scarica. Passa tutti gli URL necessari; vengono scaricati in parallelo e devono tutti consentire CORS.

listMeshes()Promise<MeshInfo[]>

Tutti i modelli importati, con i conteggi di triangoli e texture. Leggi `unitSource` e `upAxisSource` prima di fidarti dei valori accanto.

removeMesh(meshId?) · clearMeshes()Promise<void>

Rimuove un'importazione e libera geometria, materiali e texture, oppure rimuovile tutte.

setMeshVisible(visible, meshId?)Promise<void>

Mostra o nasconde un'importazione senza scaricarla.

fitMesh(meshId?)Promise<void>

Inquadra la camera su un'importazione, o su tutte.

setMeshPlacement(placement, meshId?)Promise<void>

Posiziona un'importazione a mano: posizione, imbardata, livellamento, scala. Parziale e limitato. Le importazioni partono centrate sull'IFC, appoggiate al suo piano.

setMeshUpAxis(axis, meshId?)Promise<void>

Corregge l'asse verticale dell'origine. Ha senso solo per OBJ — la specifica glTF impone Y in alto, quindi riporta `upAxisSource: 'declared'`.

setMeshUnit(unitScale, meshId?)Promise<void>

Corregge l'unità di origine: 1 metri, 0,01 centimetri, 0,001 millimetri, 0,3048 piedi. Nessuno di questi formati la registra, il visualizzatore la deduce dalla dimensione.

Conformità IDS ed EIR

checkIds(idsXml)Promise<IdsResult>

Verifica il modello rispetto a un IDS di buildingSMART (XML .ids). Gira in un worker. Restituisce superato/non superato per specifica.

checkEir(profile)Promise<IdsResult>

Verifica il modello rispetto a un profilo di validazione EIR / BIM — un oggetto, il suo JSON (incl. la forma compatta) o l'id di un profilo integrato come 'builtin-en14351-1'. Compilato in IDS ed eseguito dallo stesso motore: stesso IdsResult di checkIds.

Lingue

setLanguage(lang)void

Cambia la lingua dell'interfaccia a runtime.

getLanguages()string[]

Elenca i codici lingua supportati (etichette in IfcViewer.LANGUAGES).

Ciclo di vita ed eventi

whenReady()Promise<void>

Si risolve quando il viewer è pronto ad accettare comandi.

isReadyboolean

Getter — true non appena il viewer ha segnalato di essere pronto.

on(event, cb)() => void

Iscriviti a un evento; restituisce una funzione di annullamento.

off(event, cb)void

Rimuove un listener di eventi aggiunto in precedenza.

dispose()void

Smonta il viewer e rimuovi l'iframe.

Le chiamate concorrenti a add() / addFromUrl() sono serializzate internamente e ogni promise è correlata al proprio caricamento — un caricamento avviato dall’app (parametro URL, upload dentro l’iframe) non risolve mai la tua promise di add().

Opzioni del costruttore

OpzioneTipoPredefinitoDescrizione
ui'minimal' | 'full' | 'kiosk' | 'client' | 'article' | 'embed''minimal'Preset dell’interfaccia. 'embed': per un’app ospite che fornisce il file — 3D, proprietà alla selezione, una barra compatta con Valida e Misura; senza Apri, Condividi, account né lingua.
toolbarbooleanpresetMostra la barra degli strumenti (di default, quella del preset). false lascia la vista 3D e i pannelli.
tools('validate' | 'measure')[]['validate', 'measure']Strumenti della barra compatta di ui: 'embed' — 'validate', 'measure'. [] per nessuno.
autoFramebooleantrueInquadra tutta la scena in iso, con margine, ogni volta che un caricamento termina. false lascia a te la camera.
validatebooleantrueEsegue la validazione al caricamento (alimenta l’Health Score).
panelbooleanfalseApre automaticamente il pannello di validazione.
panelsPanelName[]—Limita la barra degli strumenti a questi pannelli, dal primo fotogramma — `['scene','map']`, oppure `[]` per nessuna barra. Stessi nomi di setPanels e del parametro URL `panels=`. Preferibile a chiamare setPanels dopo il caricamento, che mostra la barra completa e poi toglie strumenti.
langstringautoForza la lingua dell’interfaccia (es. en, es, ja).
accent#rrggbbbrandColora il viewer in tinta con la tua dashboard.
modelstring—Carica automaticamente questo URL IFC pubblico non appena pronto.
backgroundBackgroundSpec—Sfondo della scena dal primo fotogramma — un preset, '#rrggbb' o '#alto,#basso'.
mapboolean | ('terrain' | 'buildings' | 'showcase')[]—Colloca il modello sulla mappa al caricamento: true, o i livelli ['terrain','buildings','showcase'].
solar · moon'MM-DDTHH:MM' · boolean—Apre lo studio solare a un'ora locale del sito: '06-21T18:00'.
scansstring[]—URL di nuvole di punti da caricare insieme al modello.
layersstring—Configurazione di livelli di dati da aprire: l’URL di un JSON esportato dal pannello Livelli di dati (fonti dal vivo, stili, avvisi). Dalla 1.16.
scenestring—Scena da aprire: l’URL di un documento di scena (modelli, livelli di dati, dispositivi in tempo reale, mappa, camera). Dalla 1.17.
view · fillCameraView · number—Quando tutti i modelli sono caricati, inquadrarli stretti da questa vista. ui: 'article' implica 'iso'.
wheel'always' | 'ctrl''always''ctrl': la rotellina scorre la pagina e fa zoom solo con Ctrl/⌘ premuto, come una mappa incorporata. ui: 'article' lo implica.
lazyboolean | 'visible'falseNon caricare nulla finché non serve: true mostra un poster con pulsante, 'visible' si avvia quando la figura si avvicina allo schermo.
poster · posterTitle · posterText · launchLabelstring—Immagine, titolo, testo ed etichetta del pulsante del poster, finché il visualizzatore non è pronto.
aspectRatiostring ('16/10')—Dimensione per proporzione ('16/10'): poster e visualizzatore condividono il riquadro, nulla si sposta nella pagina.
turntableboolean | numberfalseLenta rotazione dopo il caricamento (true = 6°/s, o gradi al secondo).
pauseOffscreenbooleanui === 'article'Non renderizzare fuori schermo. true di default con ui: 'article'.
fullscreenButtonbooleanfalseUn piccolo pulsante di ingrandimento nell’angolo.
height · widthnumber | string'100%'Dimensione dell’iframe (numero → px).
baseUrlstringautoURL base dell’app. Ricavato dall’URL dello script.
loadTimeoutnumber120000Rifiuta add()/addFromUrl() dopo N ms (0 disattiva).
className · titlestring—Classe aggiuntiva / title dell’iframe.
on* callbacksfunction—Callback di comodo — equivalenti a .on(...).

Eventi

EventoPayloadDescrizione
ready{ languages }Viewer montato e pronto.
model-progress{ percent, phase }Avanzamento del caricamento (download → parsing → render).
model-loaded{ modelId, fileName, elementCount, fromCache }Un modello ha finito di caricare.
validation-started{ modelId }È iniziata una validazione su un modello — dopo un caricamento (validate: true) o da validate().
validation-completed{ modelId, qualityScore, errors, warnings, info, total }Validazione completata: l’Health Score e i conteggi, e il modello a cui si riferiscono (null per l’aggregato federato).
validation-failed{ modelId, message }Una validazione non è potuta partire o non è terminata — con il motivo.
model-error{ message, url?, name? }Un caricamento è fallito.
element-selected{ expressId, modelId, ifcType, name, globalId }L’utente ha scelto un elemento — con il suo GlobalId, per collegarlo ai tuoi dati.
pointcloud-picked{ cloudId, position, sourcePosition, classification, intensity, distance }È stato letto un punto da una scansione, nelle coordinate del file e non della scena.
map-feature-picked{ id, name?, label?, featureKind, heightM?, heightEstimated }È stato cliccato un edificio dei dintorni OpenStreetMap. Contesto, non modello.
walk-changed{ active, speed }La modalità passeggiata è stata attivata o disattivata — dal visitatore o dall'host.
measurements-changed{ tool, units, items }Una misura è stata aggiunta, rimossa o rinominata. Contiene l’elenco completo.
tour-started{ title, total, template }È iniziato un tour.
tour-step{ index, total, caption }Il tour è passato a un’altra sosta.
tour-ended{ completed }Il tour si è fermato; completed se ha raggiunto l’ultima sosta.
presentation-progress{ stage, label?, progress }Il regista sta generando o esportando una presentazione.
layer-feature-picked{ layerId, layer, featureId, geometry, lonLat, properties }È stato cliccato un elemento di un livello di dati: il suo livello, le proprietà e un punto da segnare.
alert{ kind, from, id, name, rule, count, sample }Una regola di un livello di dati o del gemello ha iniziato o smesso di segnalare un allarme.

Membri statici

IfcViewer.LANGUAGES ({ code, label }[], nomi nativi) e IfcViewer.SUPPORTED_LANGUAGES (codici) — per costruire un selettore di lingua prima che il viewer sia pronto.

Web component

Zero JavaScript — metti il tag in qualsiasi pagina o dashboard e imposta gli attributi.

Attributi: modeluilangaccentvalidatepanelbase-urltoolbartoolsauto-frame

Gli eventi vengono riemessi come CustomEvent del DOM chiamati ifcviewer:<type> (detail = payload). L’IfcViewer sottostante è su .viewer dell’elemento; getStats / getIssues / screenshot sono delegati a esso.

JavaScript
const el = document.querySelector("ifc-viewer");
el.addEventListener("ifcviewer:validation-completed", (e) => {
  updateScore(e.detail.qualityScore);
});
const stats = await el.getStats();

Guide

Ricette

Pattern da copiare e incollare, per quello che i team costruiscono davvero.

Ispettore di elementi

Clicca nel 3D e porta i property set IFC nel tuo pannello.

JavaScript
viewer.on("element-selected", async (e) => {
  const data = await viewer.getElement(e.expressId, e.modelId);
  renderPanel(data.name, data.globalId, data.propertySets);
});

Widget Health Score

Mostra il punteggio di qualità del modello e il conteggio dei problemi nella tua dashboard.

JavaScript
viewer.on("validation-completed", (v) => {
  setScore(v.qualityScore);                 // 0–100, or null
  setCounts(v.errors, v.warnings, v.info);
});

Verifica di conformità IDS

Valida contro un IDS di buildingSMART ed elenca superato / non superato per specifica.

JavaScript
const ids = await fetch("/specs/project.ids").then(r => r.text());
const res = await viewer.checkIds(ids);     // runs in a worker

res.specs.forEach((spec) => {
  row(spec.name, spec.status, spec.passedCount + "/" + spec.applicableCount);
  spec.failures.forEach((f) => onClick(() => viewer.select(f.expressId, f.modelId)));
});

Validazione EIR / BIM

Esegui un profilo EIR modificabile (in stile ISO 19650) — senza file .ids. I fallimenti portano il GlobalId dell’elemento.

JavaScript
// An editable EIR profile — object, JSON, or the compact shorthand below.
const profile = {
  name: "Door QA",
  rules: [
    { type: "requiredProperty", entity: "IfcDoor", property: "FireRating", severity: "error" },
    { type: "allowedValues", entity: "IfcDoor", property: "FireRating",
      values: ["EI30", "EI60", "EI90"], severity: "warning" },
  ],
};
const res = await viewer.checkEir(profile);   // same IdsResult as checkIds
res.specs.forEach((spec) => {
  spec.failures.forEach((f) => row(spec.name, f.globalId, f.reasons.join(" · ")));
});

Una scena per un articolo di blog

Sfondo bianco, il modello nel suo sito e l’ombra serale del solstizio d’estate — dichiarato in anticipo, senza clic.

JavaScript
// Declared up front: the iframe boots with all of it, no clicks, no flash.
const viewer = await IfcViewer.create("#viewer", {
  model: "https://example.com/house.ifc",
  ui: "client",
  background: "white",
  map: ["terrain", "buildings"],   // your page declares tile consent
  solar: "06-21T19:30",            // summer solstice, site-local
});

// …or change the story as the reader scrolls
await viewer.setSolar({ date: "12-21", time: "09:30" });
const { attributions } = await viewer.getSiteContext(); // show these

Pianta e misure

Taglia una pianta a un livello per nome, lascia misurare il lettore e rileggi i risultati in unità SI.

JavaScript
const { levels } = await viewer.getSections();
await viewer.addSection({ level: levels[0].name });   // floor plan, 1.2 m up
viewer.setView("top");

await viewer.setMeasureTool("distance");
viewer.on("measurements-changed", ({ items }) => {
  // value is SI — metres, m², degrees — whatever the viewer displays
  render(items.map((m) => m.kind + ": " + m.value?.toFixed(2)));
});

Un tour guidato in un articolo

Definisci le soste una volta con getCamera(), poi lascia che il tour scorra da solo accanto al testo.

JavaScript
// 1. Once, while writing the post: frame each view and copy the camera.
console.log(JSON.stringify(await viewer.getCamera()));

// 2. In the page: play the stops, self-running, next to your text.
await viewer.playTour({
  title: "Casa Poblenou",
  steps: [
    { position: { x: 52, y: 29, z: 24 }, target: { x: 18, y: 7, z: -11 }, caption: "The site" },
    { position: { x: 18, y: 40, z: 11 }, target: { x: 18, y: 0, z: 10 },
      caption: "Structure", isolate: ["IfcColumn", "IfcSlab"] },
  ],
}, { autoplay: 6000 });
viewer.on("tour-step", ({ index, caption }) => highlightParagraph(index));

Un video del modello, dalla tua pagina

Genera una presentazione con una ricetta e ricevi l’MP4 — senza registrare lo schermo, senza upload.

JavaScript
viewer.on("presentation-progress", ({ stage, progress }) => bar.value = progress ?? 0);
await viewer.createPresentation("linkedin-teaser", { title: "Casa Poblenou", targetSec: 20 });

const { bytes, mimeType } = await viewer.exportPresentation({ resolution: 1080 });
video.src = URL.createObjectURL(new Blob([bytes], { type: mimeType }));

Una copertina per il tuo post

Genera un pin Pinterest o una card LinkedIn del modello con il tuo titolo e ricevi il PNG.

JavaScript
await viewer.createCover({
  recipe: "pinterest",
  text: { title: "Casa Poblenou", location: "Barcelona", website: "https://example.com" },
});
const { bytes, mimeType } = await viewer.exportCover({ type: "png" });
img.src = URL.createObjectURL(new Blob([bytes], { type: mimeType }));

Un modello dentro un articolo

ui: 'article' è solo il canvas, inquadrato perché il modello lo riempia, con una rotellina che lascia continuare a leggere. L’angolo si sceglie con frame().

JavaScript
const viewer = new IfcViewer("#figure", {
  ui: "article",            // canvas only, tight iso framing, wheel scrolls the page
  model: "https://example.com/pavilion.ifc",
  lazy: true,               // nothing loads until the reader asks
  poster: "/img/pavilion.jpg",
  posterTitle: "The pavilion, live",
  aspectRatio: "16/10",     // no layout shift from poster to viewer
  background: "auto",       // paper on a light page, studio on a dark one
  turntable: true,          // a slow turn until the reader takes over
  fullscreenButton: true,
  validate: false,
});

Una storia che avanza con il testo

Fissa il visualizzatore e lascia che ogni paragrafo scelga l’inquadratura: isola i muri, gira intorno, porta il sole della sera.

JavaScript
// <div id="figure" style="position:sticky;top:1rem"></div>
// <p id="s1">…</p> <p id="s2">…</p> <p id="s3">…</p>
const viewer = new IfcViewer("#figure", { ui: "article", aspectRatio: "16/10", model: url });
viewer.bindSteps([
  { el: "#s1", frame: { view: "iso" } },
  { el: "#s2", isolate: "IfcWall", frame: { azimuth: 225, elevation: 20 } },
  { el: "#s3", isolate: null, solar: { active: true, date: "06-21", time: "19:30" } },
]);

Un gemello di città in tempo reale nella tua pagina

Apri una scena pubblicata, reagisci ai suoi allarmi e clic, aggiungi la tua fonte in tempo reale accanto e condividi un link al risultato.

JavaScript
const viewer = new IfcViewer("#twin", {
  ui: "client",
  scene: "https://www.ifcvieweronline.eu/scenes/barcelona-placa-catalunya.scene.json",
});
viewer.on("alert", (a) => { if (a.kind === "start") notify(a.name + ": " + a.rule) });
viewer.on("layer-feature-picked", (f) => showCard(f.layer, f.properties));

// Your own live source next to the scene's (GeoJSON with CORS, every 60 s)
await viewer.addLayer({ url: "https://example.org/sensors.geojson", live: 60 });
const { link, sources } = await viewer.exportScene({ title: "Our twin" });

Una scheda prodotto nella tua app

Fissa la versione, passa il file e mostra ciò che il produttore ha messo nel tipo: trasmittanza, classe di carico del vento, produttore.

JavaScript
import { IfcViewer } from "https://www.ifcvieweronline.eu/sdk/1.18.0/ifc-viewer.es.js";

const viewer = await IfcViewer.create("#product-3d", {
  ui: "embed",               // 3D + properties, Validate and Measure only
  panels: ["properties"],
  lang: "es",
});
const bytes = await fetch(product.ifcUrl).then(r => r.arrayBuffer());
await viewer.add("V-70-PR.ifc", bytes);                      // framed for you

// The product, by class (or by its GlobalId) — no expressIDs to know
const [win] = await viewer.findElements({ ifcClass: "IfcWindow" });

// What the manufacturer put in the type (IfcWindowType → HasPropertySets)
const el = await viewer.getElement(win.globalId);
const pset = (name) => el.effectivePropertySets.find(s => s.name === name);
const uw = pset("Pset_WindowCommon")?.properties.find(p => p.name === "ThermalTransmittance");
console.log(el.typeName, el.globalId, uw?.value, uw?.unit);   // "Ventana V-70 practicable" … 1.2 "W/(m²·K)"

const { qualityScore } = await viewer.validate();             // Health Score, on demand

// Declared performance per EN 14351-1: wind, water, acoustics, Uw, g / τv, DoP
const en = await viewer.checkEir("builtin-en14351-1");
const missing = en.specs.filter(s => s.status === "fail").map(s => s.name);

Adattalo al tuo brand

Allinea il viewer al tuo prodotto con un solo colore d’accento.

JavaScript
new IfcViewer("#viewer", { accent: "#3fa866" });

// …or on the web component:
// <ifc-viewer accent="#3fa866" model="…"></ifc-viewer>

Selettore di lingua

Costruisci un selettore dalle lingue incluse nel viewer.

JavaScript
// build a <select> from the bundled languages
IfcViewer.LANGUAGES.forEach(({ code, label }) => addOption(code, label));

// switch at runtime
viewer.setLanguage("ja");

Health Score

Ciclo della validazione

validate: true valida ogni modello appena caricato; validate() la esegue su richiesta e risolve con il risultato. Cosa restituisce getValidation() momento per momento:

QuandogetValidation() restituisce
Prima di qualsiasi validazionenull — getValidationStatus() dice idle.
Durante la prima esecuzionenull — getValidationStatus() dice running, con avanzamento; validation-started è già stato emesso.
Dopo un’esecuzione{ qualityScore, errors, warnings, info, total, status: 'done', modelId }. Con più modelli, l’aggregato (modelId: null).
Durante un’esecuzione più recenteI numeri precedenti, con status: 'running'.
Dopo un erroreI numeri precedenti con status: 'error' ed error — o null se non c’erano. È stato emesso validation-failed e validate() ha rifiutato.

Versioni

Fissa una versione

Dalla 1.18.0, ogni versione è pubblicata anche in un percorso che non cambia mai. Fissala in produzione; il percorso mobile segue l’ultima versione.

HTML
<script type="module">
  import { IfcViewer } from "https://www.ifcvieweronline.eu/sdk/1.18.0/ifc-viewer.es.js";
</script>
PercorsoCacheUso
/sdk/ifc-viewer.es.jsriconvalidato a ogni caricamentoPer provare — sempre l’ultima.
/sdk/1.18.0/ifc-viewer.es.jsimmutabile, in cache per un annoProduzione — il codice testato è il codice che gira.

Quale viewer apre un SDK fissato?

L’iframe è il viewer dal vivo della stessa origine, non una copia congelata: un SDK fissato mantiene la sua API e il suo comportamento mentre il viewer al suo interno continua a migliorare. Il viewer risponde a ogni comando di qualsiasi SDK pubblicato — il build lo verifica —, quindi una vecchia versione fissata continua a funzionare.

Fissa anche il contenuto

versions.json, accanto all’SDK, elenca l’hash Subresource Integrity di ogni versione:

HTML
<script type="module" src="https://www.ifcvieweronline.eu/sdk/1.18.0/ifc-viewer.es.js"
        integrity="sha384-WsT4d0DS1oqva4rLWCGBDrx50uZVA3B95IDWbfxaFt8lnjs6NgOrjKNcWQL57/0z" crossorigin="anonymous"></script>

Registro delle modifiche

1.18.0 — oggetti di catalogo in un’app ospite. getElement() restituisce il GlobalId e i dati del tipo (typeName, typeProperties con unità, effectivePropertySets; tipi IFC4 e stili IFC2x3). validate(), getValidationStatus(), validation-started / validation-failed, e validate: true valida davvero dopo ogni caricamento. Inquadratura automatica dopo il caricamento, fit() e frame() con margine per oggetti piccoli, frame(elementId), e setView() muove di nuovo la camera. ui: 'embed' con toolbar e tools. Versioni fisse in /sdk/1.18.0/. findElements(), GlobalId in getElement() / select() / element-selected, set di telaio e anta di finestre e porte, e i materiali del tipo; in ui: 'embed' il pannello delle proprietà lascia in vista l’oggetto scelto. checkEir('builtin-en14351-1') verifica le prestazioni dichiarate di finestre e porte esterne secondo la EN 14351-1 — vento, tenuta all'acqua, acustica, trasmittanza termica, g e τv, fabbricante e codice prodotto — nei property set IFC standard; le regole EIR acquisiscono where (solo elementi con un valore di proprietà) e optional.

Aiuto

Risoluzione dei problemi

Le poche cose su cui si inciampa.

Non viene renderizzato nulla

Controlla, in quest’ordine: che il viewer abbia raggiunto ready, che il modello sia stato caricato (model-loaded invece di model-error), che il contenitore abbia altezza diversa da zero e che la sorgente di byte sia IFC valido. Il messaggio di model-error indica la causa.

Ricevo un errore CORS caricando un modello

Il CORS riguarda solo addFromUrl(url). Se controlli i byte, scaricali tu e chiama add(name, bytes) — il CORS non si applica perché consegni i dati direttamente.

L’iframe resta bianco o si rifiuta di caricare

L’app deve essere incorporabile — niente X-Frame-Options: DENY e nessuna CSP frame-ancestors restrittiva sull’host. La nostra app ospitata consente l’incorporamento.

Il mio ArrayBuffer è vuoto dopo add()

add() trasferisce il buffer per una consegna senza copia, il che lo lascia detached nel tuo codice. Passa una copia (bytes.slice(0)) se ti servono ancora i byte dopo.

I caricamenti o le query vanno in timeout

add()/addFromUrl() vengono rifiutate dopo loadTimeout (120 s di default; 0 disattiva). Le query dopo 30 s, checkIds dopo 120 s. Modelli grandi su dispositivi lenti possono richiedere un loadTimeout più alto.

Quali browser sono supportati?

Qualsiasi browser moderno con WebAssembly e moduli ES — Chrome, Edge, Firefox, Safari. Niente Internet Explorer.

Ottengo un 404 sul mio server di sviluppo locale

Un dev server SPA può intercettare /sdk/ con il suo fallback HTML. Prova con una build reale o un hosting statico, oppure importa direttamente il modulo /sdk/ifc-viewer.es.js.