IFC Viewer SDK v1.18.0 Abrir o visualizador
Português

IFC Viewer SDK · v1.18.0

Incorpore o visualizador IFC no seu próprio produto

Insira o mesmo visualizador do navegador no seu CDE, gémeo digital ou ferramentas internas de projeto. Carregue dados IFC da sua app enquanto cada modelo é analisado no cliente.

Três linhas até ao primeiro render

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

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

Instalação

Início rápido

Escolha a sua stack. Copie, cole e renderize — sem passo de build, sem chave de 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>

Alojado por nós ou por si

Os exemplos importam do nosso CDN, que funciona em qualquer origem. Para alojar por si, sirva ifc-viewer.es.js a partir do seu domínio — o SDK descobre o URL da aplicação relativamente ao script. A aplicação está noutro sítio? Use a opção baseUrl.

Ainda não há pacote npm: importe o módulo por URL (acima) ou incorpore ifc-viewer.es.js na sua aplicação.

Demonstração

Demo ao vivo

Esta página está a executar o SDK. Clique num controlo para obter um IFC de exemplo e conduzir o visualizador — cada botão mostra a chamada que faz.

inativo
Última chamada —

Arquitetura

Como funciona

Um wrapper mínimo na sua página, o visualizador completo num iframe isolado, os seus bytes a atravessar — e processados onde já estavam.

Navegador do visitante — nada é enviadoA sua aplicaçãoSDK · ~6 KBiframe isoladothree.js · web-ifc · WASMBytes IFCpostMessage

A sua aplicação

Um módulo ES de ~6 KB que cria um iframe e uma API JS tipada. Nada do peso de 3D nem de parsing toca no seu bundle.

Ponte postMessage

Os bytes IFC são transferidos para o iframe como ArrayBuffer (sem cópia). Comandos e consultas são mensagens correlacionadas de pedido/resposta.

O visualizador

three.js + web-ifc compilado para WebAssembly fazem o parsing e o render do modelo dentro do iframe — na máquina do visitante.

Porque é privado

Os modelos nunca chegam a um servidor. Nenhuma cadeia de upload para proteger, nenhuma questão de residência de dados, nenhuma fila por tamanho de ficheiro.

Porque escala

O cálculo corre no dispositivo de cada visitante. Servir um modelo de 200 MB custa o mesmo que um de 2 MB — é um ficheiro estático.

Conceitos

Conceitos essenciais

Quatro coisas a saber antes de construir.

Montagem e prontidão

new IfcViewer(target) monta de imediato e põe os comandos em fila até o visualizador estar pronto. await IfcViewer.create(target) (ou whenReady()) devolve uma instância utilizável de imediato.

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");

Bytes ou URL

add(name, bytes) transmite bytes que já tem — sem CORS e sem enviar nada; o buffer é transferido (fica detached), por isso passe uma cópia se ainda precisar dele. addFromUrl(url) descarrega um URL público com CORS.

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");

Eventos

Subscreva com on(event, cb), que devolve uma função para cancelar a subscrição. Tem ready, model-progress, model-loaded, validation-completed, model-error e element-selected.

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

Consultas

Obtenha dados a pedido: getModels, getElement, getValidation, getStats, getIssues, checkIds, checkEir, screenshot. Cada uma é pedido/resposta e é rejeitada após um tempo limite (30 s; IDS / EIR até 120 s).

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

Referência

Referência da API

Todos os métodos, agrupados — com assinaturas e tipos de retorno. A seguir vêm as opções do construtor, os eventos e o web component <ifc-viewer>.

Construtor

new IfcViewer(target, options?)IfcViewer

Montar num seletor CSS ou elemento. Veja as opções abaixo.

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

Cria um visualizador e resolve assim que estiver pronto para aceitar comandos.

Carregamento de modelos

add(name, bytes)Promise<ModelLoadedEvent>

Carregar bytes IFC (ArrayBuffer/Uint8Array) da sua app. O buffer é transferido para uma passagem sem cópia.

addFromUrl(url, name?)Promise<ModelLoadedEvent>

Carregar um URL IFC público com CORS.

removeModel(modelId)void

Descarrega um modelo por id.

clear()void

Remover todos os modelos carregados.

Câmara e seleção

select(expressId | globalId, modelId?)void

Selecionar e enquadrar um elemento — pelo seu expressID IFC ou pelo GlobalId (que também encontra o modelo).

setView(view)void

Voar para uma vista com nome da cena — iso, front, back, left, right, top, bottom — com toda ela no enquadramento. Sem resposta (entre 1.14 e 1.17 o visualizador ignorava-a).

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

Enquadramento para apresentar: o modelo ocupa `fill` do quadro (0,2–0,98, por omissão 0,85), ajustado aos seus cantos e não à esfera envolvente. azimuth / elevation olham de qualquer ângulo.

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

Enquadrar um elemento (expressID): a partir do ângulo atual, salvo se for indicada uma vista. Rejeita se não estiver no modelo.

fit() · reset()void

Enquadrar o modelo ativo a partir do ângulo atual, com margem / repor a câmara.

setCamera(position, direction)void

Coloca a câmara numa posição a olhar numa direção.

getCamera()Promise<CameraState | null>

Onde está a câmara e para onde olha — guarde e restaure com lookAt.

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

Leva a câmara a uma posição a olhar para um alvo (metros de cena, Y para cima).

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

Modo passeio na primeira pessoa (WASD, arrastar para olhar, Esc para sair). Emite walk-changed.

getWalkState()Promise<WalkState>

Se o modo passeio está ativo e a que velocidade.

Visibilidade

isolate(ifcType?)void

Isolar uma categoria (ex.: "IfcWall"); omitir para limpar.

showAll()void

Restaurar toda a visibilidade (limpar ocultos + isolamento).

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

Oculta / mostra um conjunto de elementos por expressID.

setModelVisible(modelId, visible)Promise<void>

Mostra ou oculta um modelo de uma cena federada sem o descarregar.

setModelOpacity(opacity, modelId?)Promise<void>

Torna um modelo translúcido (0,05–1) — p. ex. a arquitetura à volta das instalações.

isolateModel(modelId | null)Promise<void>

Mostra só este modelo; null volta a mostrá-los todos.

Aspeto e apresentação

setBackground(background)Promise<BackgroundState>

Muda o fundo da cena: um preset ('white', 'paper', 'blueprint', 'sky', 'studio'), '#rrggbb', '#cima,#baixo' ou { top, bottom }. Não é guardado como preferência do visitante.

getBackground()Promise<BackgroundState>

O fundo atual da cena.

setAccent(color)Promise<void>

Muda a cor de destaque da interface em tempo de execução (#rrggbb).

setClientMode(enabled)Promise<void>

Liga ou desliga a vista cliente — a de apresentação a stakeholders, igual a ui: 'client'.

setRenderQuality(quality)Promise<void>

'quality' ativa a renderização mais pesada para uma imagem de destaque; 'standard' para o dia a dia.

Estudo solar

setSolar(opts?)Promise<SolarState>

Sombras reais numa data e hora locais do local: { date: '06-21', time: '18:00' }. O local vem da georreferência do IFC; passe location para um modelo sem ela — nunca uma cidade por omissão em silêncio.

getSolar()Promise<SolarState>

Data, hora e fuso do estudo, e onde fica o local.

Modo mapa

setSiteContext(opts?)Promise<SiteContextState>

Coloca o modelo no mapa com terreno e envolvente OpenStreetMap. Chamá-lo é a sua página a declarar o consentimento de mosaicos pelos visitantes; mostre as atribuições.

getSiteContext()Promise<SiteContextState>

Estado do modo mapa, a colocação e as atribuições a mostrar.

Cenas

openScene(url | SceneDocument)Promise<void>

Abrir outra cena: o URL de um .scene.json ou um documento de cena (viaja comprimido no endereço da moldura, por isso tem de caber numa ligação). O visualizador recarrega com ela; as chamadas pendentes são rejeitadas e ready volta a disparar.

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

A cena no ecrã como documento de cena — modelos por URL, camadas, gémeo, mapa, câmara — com as fontes a creditar e uma ligação que a contém.

packScene(doc)Promise<string | null>

Comprimir você mesmo um documento de cena para uma ligação #scene= (null se for grande demais para uma ligação).

Camadas de dados e gémeo

getLayerPresets()Promise<LayerPreset[]>

O catálogo de fontes públicas em direto, com nome no idioma do visualizador, o que cada uma precisa num navegador (uma chave, um proxy) e se tem dados perto do local.

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

Adicionar uma camada: uma fonte do catálogo ({ preset }), GeoJSON ou um feed em direto num URL ({ url, live }), ou GeoJSON que já tem ({ geojson }). Só para a sessão: nunca guardada nas camadas do visitante.

getLayers()Promise<DataLayerInfo[]>

Todas as camadas de dados: estado, número de elementos, extensão, atualização e atribuição.

setLayerVisible(id, visible)Promise<DataLayerInfo>

Mostrar ou ocultar uma camada.

frameLayer(id)Promise<void>

Levar a câmara aos elementos de uma camada.

removeLayer(id)Promise<void>

Remover uma camada.

getTwin()Promise<TwinState>

O gémeo operacional agora: fontes de dispositivos (estado, última leitura) e, por ligação, a regra que se cumpre, a sua cor, o valor da etiqueta e se está em alerta.

Cortes

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

Adiciona um plano de corte. { level: 'Piso 1' } é uma planta nesse piso; { axis: 'x', offset: 4.5 } um corte a 4,5 m.

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

Move, liga/desliga ou inverte um plano.

removeSection(id?)Promise<SectionsState>

Remove um plano, ou todos os cortes sem id.

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

Uma caixa de corte à volta do modelo ou da seleção; false remove-a.

getSections()Promise<SectionsState>

Todos os planos, a caixa e os pisos disponíveis para cortes por nível.

Tours

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

Inicia um tour predefinido: 'social', 'client-walkthrough' ou 'technical-review' (percorre as incidências de validação). Reproduzido pela barra de tour do visualizador.

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

Reproduz um tour criado por si: paragens de câmara com legendas, destaques e classes isoladas. autoplay: true ou ms por paragem.

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

Mudar de paragem.

setTourAutoplay(autoplay)Promise<TourState>

Liga ou desliga o avanço automático do tour em curso.

stopTour()Promise<TourState>

Para o tour e devolve a câmara.

getTour()Promise<TourState>

O tour e as suas paragens, no formato de playTour() — guarde-o e reproduza-o mais tarde.

Realizador de apresentações

getPresentationRecipes()Promise<PresentationRecipe[]>

As receitas do realizador (demo para reunião, reel, teaser do LinkedIn, lançamento, looks editoriais…).

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

Transforma o modelo num vídeo editado a partir de uma receita: planos gerados do IFC, legendas, música. Abre o Clip Studio com o resultado. Acompanhe presentation-progress.

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

Codifica a apresentação no navegador do visitante e devolve os bytes do MP4 — para enviar, anexar ou reproduzir num <video>.

closePresentation()Promise<void>

Fecha o Clip Studio.

Estúdio de capas

getCoverOptions()Promise<CoverCatalog>

As receitas, modelos, formatos e paletas do estúdio de capas.

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

Cria uma capa: executa uma receita (captura as vistas de que precisa) e depois define modelo, formato, paleta e textos. Abre o estúdio, que continua editável.

getCover()Promise<CoverState | null>

A capa tal como está, ou null se o estúdio estiver fechado.

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

Exporta-a: png / jpeg (uma página), pdf / pptx (todo o documento), zip (todas as páginas). Devolve os bytes.

closeCover()Promise<void>

Fecha o estúdio de capas.

Kit de artigo

activate()void

Arrancar já um visualizador diferido (o que faz o botão do póster). As chamadas anteriores ficaram em fila.

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

Scrollytelling: enquanto cada parágrafo cruza o meio do ecrã, enquadrar, isolar, mover o sol ou correr o seu código. Devolve uma função para desligar.

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

Uma rotação lenta em repouso (graus por segundo; false para-a). Para ao primeiro toque, nunca com movimento reduzido.

toggleFullscreen()Promise<void>

Ampliar a figura para ecrã inteiro, ou voltar.

setPaused(paused)Promise<{ paused }>

Parar ou retomar a renderização. pauseOffscreen fá-lo por si.

Grupos de cena

getGroups()Promise<SceneGroupsState>

Todos os grupos da cena — deduzidos do IFC (projeto, local, localização) e criados pelos utilizadores.

createGroup(name, modelIds?)Promise<string>

Cria um grupo, opcionalmente com modelos. Devolve o seu id.

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

Muda o nome ou apaga um grupo de utilizador. Os automáticos não se editam.

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

Move um modelo ou nuvem de pontos para um grupo; null devolve-o ao agrupamento automático, 'loose' deixa-o sem grupo.

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

Mostra ou oculta um grupo inteiro, ou mostra só um.

frameGroup(id)Promise<void>

Enquadra a câmara num grupo, incluindo membros ocultos.

Medições

setMeasureTool(tool)Promise<void>

Arma uma ferramenta de medição para o visitante (abre o painel Medir), ou 'none'. Os resultados chegam em measurements-changed.

getMeasurements()Promise<MeasurementsState>

Todas as medições no ecrã. Valores em SI — metros, m², graus — seja qual for a apresentação.

clearMeasurements(id?)Promise<MeasurementsState>

Remove uma medição, ou todas.

Consultas

getModels()Promise<ModelSummary[]>

Lista os modelos carregados. Devolve uma promessa.

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

Encontrar elementos por classe IFC, GlobalId e/ou nome nos modelos carregados. Cada resultado traz o que getElement(), select() e frame() pedem.

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

Por expressID ou GlobalId. Os dados IFC de um elemento: atributos com o GlobalId, os seus conjuntos de propriedades e quantidades, e os do seu tipo — typeName, typeProperties — com unidades. effectivePropertySets junta ambos e prevalece o valor do próprio elemento.

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

Validar um modelo agora (por omissão, o ativo) e resolver com o seu Health Score e as contagens de problemas. Rejeita com o motivo.

getValidation()Promise<ValidationSummary | null>

O resultado de validação no ecrã, ou null antes de uma execução ter produzido um. Ver «Ciclo da validação».

getValidationStatus()Promise<ValidationStatus>

Em que ponto está a validação: idle, running (com progresso), done ou error.

getStats()Promise<StatsResult>

Contagem de elementos por categoria e modelo — para gráficos. Devolve uma promessa.

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

Problemas de validação para uma tabela (filtra por severidade / limite). Devolve uma promessa.

screenshot()Promise<string>

Captura a vista 3D atual como data URL PNG. Devolve uma promessa.

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

Compara duas entregas por URL (por GlobalId) e abre a área de comparação com o resultado.

Painéis

openPanel(panel | null) · closePanel()void

Abre um painel de ferramenta, ou passa null para fechar o que estiver aberto. Um painel indisponível — escondido pelo chrome, ou sem nada carregado sobre o que atuar — não faz nada, e não é um erro.

getPanels()Promise<PanelsResult>

Que painel está aberto e quais são oferecidos neste momento. Uma ferramenta ausente de `available` não pode ser aberta; não está apenas desativada.

setPanels(panels)void

Limita a barra a estes painéis, em tempo de execução. Mesmo vocabulário do parâmetro de URL `panels=` e tem prioridade sobre ele. Restringe o que o visualizador oferece e nunca acrescenta; um array vazio significa sem barra.

Nuvens de pontos

addPointCloud(fileName, bytes)Promise<string>

Carrega um levantamento a partir de bytes — LAS, LAZ, COPC, PLY, PCD ou texto. O buffer é transferido, não copiado. Resolve com o id da nuvem.

addPointCloudFromUrl(url, fileName?)Promise<string>

Carrega um levantamento que o próprio visualizador obtém. O URL tem de permitir CORS.

listPointClouds()Promise<PointCloudInfo[]>

Todos os levantamentos carregados. `pointCount` é o residente, `declaredCount` o que o ficheiro contém — diferem quando o orçamento truncou a leitura.

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

Descarrega um levantamento e liberta os seus buffers de GPU, ou descarrega todos.

setPointCloudVisible(cloudId, visible)Promise<void>

Mostra ou oculta um levantamento sem o descarregar.

fitPointCloud(cloudId?)Promise<void>

Enquadra a câmara num levantamento, ou no primeiro carregado.

setPointCloudDisplay(display, renderBudget?)Promise<void>

Tamanho do ponto, opacidade, modo de cor, densidade, limiar de confiança — partilhados por todos. Cada um é um uniform do shader, logo instantâneo com 20 milhões de pontos.

inspectPointCloud(enabled?)Promise<void>

Arma o clique para ler. Enquanto armado, clicar num ponto emite `pointcloud-picked` com as coordenadas DO FICHEIRO ao lado das da cena.

setPointCloudPlacement(placement, cloudId?)Promise<void>

Ajusta um levantamento à mão: posição, guinada, nivelamento, escala. Parcial e limitado; aplica-se sobre o alinhamento deduzido em vez de o substituir.

setPointCloudUpAxis(axis, cloudId?)Promise<void>

Corrige que eixo o levantamento trata como vertical. PLY, PCD e texto não declaram orientação, o visualizador deduz — verifique `upAxisSource`.

Imported 3D models

addMesh(files)Promise<string>

Importa um modelo a partir de bytes. Recebe uma LISTA: um .gltf precisa do seu .bin e texturas, um .obj do seu .mtl — sozinho, o ficheiro de entrada dá geometria cinzenta.

addMeshFromUrl(urls)Promise<string>

Importa um modelo que o visualizador obtém. Passe todos os URL necessários; são obtidos em paralelo e todos têm de permitir CORS.

listMeshes()Promise<MeshInfo[]>

Todos os modelos importados, com contagens de triângulos e texturas. Leia `unitSource` e `upAxisSource` antes de confiar nos valores ao lado.

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

Remove uma importação e liberta a geometria, materiais e texturas, ou remove todas.

setMeshVisible(visible, meshId?)Promise<void>

Mostra ou oculta uma importação sem a descarregar.

fitMesh(meshId?)Promise<void>

Enquadra a câmara numa importação, ou em todas.

setMeshPlacement(placement, meshId?)Promise<void>

Coloca uma importação à mão: posição, guinada, nivelamento, escala. Parcial e limitado. As importações começam centradas no IFC, assentes no seu piso.

setMeshUpAxis(axis, meshId?)Promise<void>

Corrige o eixo vertical da origem. Só faz sentido em OBJ — a especificação glTF obriga a Y para cima, por isso reporta `upAxisSource: 'declared'`.

setMeshUnit(unitScale, meshId?)Promise<void>

Corrige a unidade de origem: 1 metros, 0,01 centímetros, 0,001 milímetros, 0,3048 pés. Nenhum destes formatos a regista, o visualizador deduz do tamanho do modelo.

Conformidade IDS e EIR

checkIds(idsXml)Promise<IdsResult>

Verifica o modelo contra um IDS da buildingSMART (XML .ids). Corre num worker. Devolve aprovado/reprovado por especificação.

checkEir(profile)Promise<IdsResult>

Verifica o modelo contra um perfil de validação EIR / BIM — um objeto, o seu JSON (incl. o formato compacto) ou o id de um perfil incorporado como 'builtin-en14351-1'. Compila para IDS e corre no mesmo motor: o mesmo IdsResult que checkIds.

Idiomas

setLanguage(lang)void

Mudar o idioma da interface em tempo de execução.

getLanguages()string[]

Listar os códigos de idioma suportados (rótulos em IfcViewer.LANGUAGES).

Ciclo de vida e eventos

whenReady()Promise<void>

Resolve quando o visualizador está pronto para aceitar comandos.

isReadyboolean

Getter — true assim que o visualizador sinaliza que está pronto.

on(event, cb)() => void

Subscrever um evento; devolve uma função para cancelar.

off(event, cb)void

Remove um listener de eventos adicionado anteriormente.

dispose()void

Desmontar o visualizador e remover o iframe.

As chamadas concorrentes a add() / addFromUrl() são serializadas internamente e cada promessa é correlacionada com o seu próprio carregamento — um carregamento iniciado pela aplicação (parâmetro de URL, upload dentro do iframe) nunca resolve a sua promessa de add().

Opções do construtor

OpçãoTipoPredefiniçãoDescrição
ui'minimal' | 'full' | 'kiosk' | 'client' | 'article' | 'embed''minimal'Preset da interface. 'embed': para uma app anfitriã que fornece o ficheiro — 3D, propriedades ao selecionar, uma barra compacta com Validar e Medir; sem Abrir, Partilhar, conta nem idioma.
toolbarbooleanpresetMostrar a barra de ferramentas (por omissão, a do preset). false deixa a vista 3D e os painéis.
tools('validate' | 'measure')[]['validate', 'measure']Ferramentas da barra compacta de ui: 'embed' — 'validate', 'measure'. [] para nenhuma.
autoFramebooleantrueEnquadrar toda a cena em iso, com margem, sempre que um carregamento termina. false deixa-lhe a câmara.
validatebooleantrueExecuta a validação ao carregar (alimenta o Health Score).
panelbooleanfalseAbre automaticamente o painel de validação.
panelsPanelName[]—Limita a barra de ferramentas a estes painéis, desde o primeiro fotograma — `['scene','map']`, ou `[]` para não ter barra. Mesmos nomes que setPanels e que o parâmetro de URL `panels=`. Preferível a chamar setPanels após a carga, que mostra a barra completa e depois retira ferramentas.
langstringautoForça o idioma da interface (ex. en, es, ja).
accent#rrggbbbrandColore o visualizador a condizer com o seu dashboard.
modelstring—Carrega automaticamente este URL público de IFC assim que estiver pronto.
backgroundBackgroundSpec—Fundo da cena desde o primeiro fotograma — um preset, '#rrggbb' ou '#cima,#baixo'.
mapboolean | ('terrain' | 'buildings' | 'showcase')[]—Coloca o modelo no mapa ao carregar: true, ou camadas ['terrain','buildings','showcase'].
solar · moon'MM-DDTHH:MM' · boolean—Abre o estudo solar a uma hora local do local: '06-21T18:00'.
scansstring[]—URLs de nuvens de pontos a carregar com o modelo.
layersstring—Configuração de camadas de dados a abrir: o URL de um JSON exportado do painel Camadas de dados (fontes em direto, estilos, alertas). Desde 1.16.
scenestring—Cena a abrir: o URL de um documento de cena (modelos, camadas de dados, dispositivos em direto, mapa, câmara). Desde 1.17.
view · fillCameraView · number—Quando todos os modelos carregam, enquadrá-los a partir desta vista, de forma justa. ui: 'article' implica 'iso'.
wheel'always' | 'ctrl''always''ctrl': a roda desloca a sua página e só faz zoom com Ctrl/⌘ premido, como um mapa incorporado. ui: 'article' implica-o.
lazyboolean | 'visible'falseNão carregar nada até ser preciso: true mostra um póster com botão, 'visible' arranca quando a figura se aproxima do ecrã.
poster · posterTitle · posterText · launchLabelstring—Imagem, título, texto e botão do póster, até o visualizador estar pronto.
aspectRatiostring ('16/10')—Tamanho por proporção ('16/10'): póster e visualizador partilham a caixa, nada se mexe na página.
turntableboolean | numberfalseRotação lenta depois de carregar (true = 6°/s, ou graus por segundo).
pauseOffscreenbooleanui === 'article'Parar de renderizar fora do ecrã. true por omissão com ui: 'article'.
fullscreenButtonbooleanfalseUm pequeno botão de ampliar no canto.
height · widthnumber | string'100%'Tamanho do iframe (número → px).
baseUrlstringautoURL base da aplicação. Deduzido do URL do script.
loadTimeoutnumber120000Rejeita add()/addFromUrl() após N ms (0 desativa).
className · titlestring—Classe extra / title do iframe.
on* callbacksfunction—Callbacks de conveniência — equivalentes a .on(...).

Eventos

EventoPayloadDescrição
ready{ languages }Visualizador montado e pronto.
model-progress{ percent, phase }Progresso do carregamento (download → análise → render).
model-loaded{ modelId, fileName, elementCount, fromCache }Um modelo terminou de carregar.
validation-started{ modelId }Começou uma validação num modelo — após um carregamento (validate: true) ou via validate().
validation-completed{ modelId, qualityScore, errors, warnings, info, total }Validação concluída: o Health Score e as contagens, e o modelo a que se referem (null para o agregado federado).
validation-failed{ modelId, message }Uma validação não pôde correr ou não terminou — com o motivo.
model-error{ message, url?, name? }Um carregamento falhou.
element-selected{ expressId, modelId, ifcType, name, globalId }O utilizador escolheu um elemento — com o seu GlobalId, para o cruzar com os seus registos.
pointcloud-picked{ cloudId, position, sourcePosition, classification, intensity, distance }Leu-se um ponto de um scan, nas coordenadas do ficheiro e não da cena.
map-feature-picked{ id, name?, label?, featureKind, heightM?, heightEstimated }Clicou-se num edifício da envolvente OpenStreetMap. Contexto, não modelo.
walk-changed{ active, speed }O modo passeio foi ligado ou desligado — pelo visitante ou pelo host.
measurements-changed{ tool, units, items }Uma medição foi adicionada, removida ou renomeada. Traz a lista completa.
tour-started{ title, total, template }Começou um tour.
tour-step{ index, total, caption }O tour passou a outra paragem.
tour-ended{ completed }O tour parou; completed se chegou à última paragem.
presentation-progress{ stage, label?, progress }O realizador está a gerar ou exportar uma apresentação.
layer-feature-picked{ layerId, layer, featureId, geometry, lonLat, properties }Clicou-se num elemento de uma camada de dados: a sua camada, propriedades e um ponto para marcar.
alert{ kind, from, id, name, rule, count, sample }Uma regra de uma camada de dados ou do gémeo começou ou deixou de alertar.

Estáticos

IfcViewer.LANGUAGES ({ code, label }[], nomes nativos) e IfcViewer.SUPPORTED_LANGUAGES (códigos) — para construir um seletor de idioma antes de o visualizador estar pronto.

Web component

Zero JavaScript — coloque a tag em qualquer página ou dashboard e defina atributos.

Atributos: modeluilangaccentvalidatepanelbase-urltoolbartoolsauto-frame

Os eventos são reemitidos como CustomEvents do DOM chamados ifcviewer:<type> (detail = payload). O IfcViewer subjacente está em .viewer do elemento; getStats / getIssues / screenshot são delegados para ele.

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

Guias

Receitas

Padrões para copiar e colar, do que as equipas constroem de facto.

Inspetor de elementos

Clique no 3D e leia os property sets IFC para o seu próprio painel.

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

Widget de Health Score

Mostre a pontuação de qualidade do modelo e a contagem de problemas no seu dashboard.

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

Verificação de conformidade IDS

Valide contra um IDS da buildingSMART e liste aprovado / reprovado por especificação.

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)));
});

Validação EIR / BIM

Execute um perfil EIR editável (ao estilo ISO 19650) — sem ficheiro .ids. As falhas trazem o GlobalId do 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(" · ")));
});

Uma cena para um artigo de blog

Fundo branco, o modelo no seu local e a sombra do fim de tarde do solstício de verão — declarado à partida, sem cliques.

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

Planta e medições

Corte uma planta num piso pelo nome, deixe o leitor medir e leia os resultados em unidades 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)));
});

Um tour guiado num artigo

Defina as paragens uma vez com getCamera() e deixe o tour avançar sozinho ao lado do texto.

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));

Um vídeo do modelo, a partir da sua página

Gere uma apresentação com uma receita e receba o MP4 — sem gravar o ecrã, sem enviar nada.

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 }));

Uma capa para o seu artigo

Gere um pin do Pinterest ou um cartão do LinkedIn do modelo com o seu título e receba o 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 }));

Um modelo dentro de um artigo

ui: 'article' é só a tela, enquadrada para o modelo a preencher, com uma roda que deixa o leitor continuar a ler. Escolha o ângulo com 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,
});

Uma história que avança com o texto

Fixe o visualizador e deixe cada parágrafo escolher o plano: isolar as paredes, rodar, trazer o sol da tarde.

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" } },
]);

Um gémeo de cidade em direto na sua página

Abra uma cena publicada, reaja aos seus alertas e cliques, junte a sua própria fonte em direto e partilhe uma ligação para o resultado.

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" });

Uma ficha de produto na sua app

Fixe a versão, entregue o ficheiro e mostre o que o fabricante pôs no tipo: coeficiente U, classe de vento, fabricante.

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);

Adapte à sua marca

Alinhe o visualizador com o seu produto usando uma única cor de destaque.

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

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

Seletor de idioma

Construa um seletor a partir dos idiomas que o visualizador traz.

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 da validação

validate: true valida cada modelo quando termina de carregar; validate() executa-a a pedido e resolve com o resultado. O que getValidation() devolve em cada momento:

QuandogetValidation() devolve
Antes de qualquer validaçãonull — getValidationStatus() diz idle.
Durante a primeira execuçãonull — getValidationStatus() diz running, com progresso; validation-started já foi emitido.
Após uma execução{ qualityScore, errors, warnings, info, total, status: 'done', modelId }. Com vários modelos, o agregado (modelId: null).
Durante uma execução mais recenteOs números anteriores, com status: 'running'.
Após uma falhaOs números anteriores com status: 'error' e error — ou null se não havia. validation-failed foi emitido e validate() rejeitou.

Versões

Fixar uma versão

Desde a 1.18.0, cada versão é também publicada num caminho que nunca muda. Fixe-a em produção; o caminho móvel segue a versão mais recente.

HTML
<script type="module">
  import { IfcViewer } from "https://www.ifcvieweronline.eu/sdk/1.18.0/ifc-viewer.es.js";
</script>
CaminhoCacheUso
/sdk/ifc-viewer.es.jsrevalidado em cada carregamentoPara experimentar — sempre a mais recente.
/sdk/1.18.0/ifc-viewer.es.jsimutável, em cache um anoProdução — o código testado é o código que corre.

Que visualizador abre um SDK fixado?

O iframe é o visualizador em direto da mesma origem, não uma cópia congelada: um SDK fixado mantém a sua API e o seu comportamento enquanto o visualizador lá dentro continua a melhorar. O visualizador responde a todos os comandos de qualquer SDK publicado — o build verifica-o —, por isso uma versão fixada antiga continua a funcionar.

Fixe também o conteúdo

versions.json, junto ao SDK, lista o hash Subresource Integrity de cada versão:

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

Registo de alterações

1.18.0 — objetos de catálogo numa app anfitriã. getElement() devolve o GlobalId e os dados do tipo (typeName, typeProperties com unidades, effectivePropertySets; tipos IFC4 e estilos IFC2x3). validate(), getValidationStatus(), validation-started / validation-failed, e validate: true valida mesmo após cada carregamento. Enquadramento automático após carregar, fit() e frame() com margem para objetos pequenos, frame(elementId), e setView() volta a mover a câmara. ui: 'embed' com toolbar e tools. Versões fixas em /sdk/1.18.0/. findElements(), GlobalIds em getElement() / select() / element-selected, conjuntos de aro e folha de janelas e portas, e os materiais do tipo; em ui: 'embed' o painel de propriedades mantém à vista o objeto escolhido. checkEir('builtin-en14351-1') verifica o desempenho declarado de janelas e portas exteriores segundo a EN 14351-1 — vento, estanquidade à água, acústica, transmissão térmica, g e τv, fabricante e código do produto — em property sets IFC padrão; as regras EIR ganham where (só elementos com um valor de propriedade) e optional.

Ajuda

Resolução de problemas

As poucas coisas em que as pessoas tropeçam.

Não é renderizado nada

Verifique, por esta ordem: se o visualizador chegou a ready, se o modelo carregou (model-loaded em vez de model-error), se o contentor tem altura diferente de zero e se a origem dos bytes é IFC válido. A mensagem de model-error indica a causa.

Recebo um erro de CORS ao carregar um modelo

O CORS só afeta addFromUrl(url). Se controla os bytes, descarregue-os você e chame add(name, bytes) — não se aplica CORS porque entrega os dados diretamente.

O iframe fica em branco ou recusa carregar

A aplicação tem de ser incorporável — sem X-Frame-Options: DENY e sem uma CSP frame-ancestors restritiva no host. A nossa aplicação alojada permite a incorporação.

O meu ArrayBuffer fica vazio depois de add()

add() transfere o buffer para o entregar sem cópia, o que o deixa detached no seu código. Passe uma cópia (bytes.slice(0)) se ainda precisar dos bytes depois.

Os carregamentos ou as consultas expiram

add()/addFromUrl() são rejeitados após loadTimeout (120 s por predefinição; 0 desativa). As consultas são rejeitadas aos 30 s e checkIds aos 120 s. Modelos grandes em dispositivos lentos podem precisar de um loadTimeout maior.

Que navegadores são suportados?

Qualquer navegador moderno com WebAssembly e módulos ES — Chrome, Edge, Firefox, Safari. Internet Explorer não.

Dá 404 no meu servidor de desenvolvimento local

Um servidor de desenvolvimento SPA pode intercetar /sdk/ com o seu fallback HTML. Teste contra um build real ou um alojamento estático, ou importe diretamente o módulo /sdk/ifc-viewer.es.js.