Hi everyone,
I am trying to set up an IFCjs viewer inside of Streamlit.
I tried this on a simple example of an array of URLs, each one pointing to a specific IFC model saved on the web.
Using st.selectbox the user can pick a specific model, on selection the URL is passed to JavaScript which initialises the IFCjs viewer and opens the 3D model.
Here is the Homepage.py:
import streamlit as st
from ifc_viewer.ifc_viewer import ifc_viewer
# List of URLs
url_list = ["https://cropka.com/TEST.ifc", "http://example2.com", "http://example3.com"]
# Dropdown selector for URLs
selected_url = st.selectbox("Select URL", options=url_list)
# Call the IFC viewer with the selected URL
ifc_viewer(selected_url)
In the “ifc_viewer” folder the following code handles passing of the URL to Java:
import streamlit as st
from streamlit.components.v1 import declare_component
# Declare the component
_ifc_viewer = declare_component("ifc_viewer", path="ifc_viewer")
def ifc_viewer(url: str):
# Call the component and pass the url
_ifc_viewer(url=url)
However in my JavaScript I am clueless why this is not being received:
import { Color } from "three";
import { IfcViewerAPI } from "web-ifc-viewer";
console.log("Streamlit object: ", window.Streamlit);
const Streamlit = window.Streamlit;
const container = document.getElementById('viewer-container')
const viewer = new IfcViewerAPI({container, backgroundColor: new Color(0xffffff)});
viewer.axes.setAxes();
viewer.grid.setGrid();
async function loadIfc(url) {
// Load the model
const model = await viewer.IFC.loadIfcUrl(url);
// Now that the model is loaded, tell Streamlit that the component is ready
Streamlit.setComponentReady();
}
Streamlit.onRender((data) => {
const url = data.args.url;
loadIfc(url);
});
Clearly the problem I get in the console is that window.Streamlit is undefined. How can I receive the URL on JavaScript’s end? Any ideas much appreciated!
import { Color } from "three";
import { IfcViewerAPI } from "web-ifc-viewer";
function sendMessageToStreamlitClient(type, data) {
const message = { ...data, isStreamlitMessage: true, type };
window.parent.postMessage(message, "*");
}
function init() {
sendMessageToStreamlitClient("streamlit:componentReady", {apiVersion: 1});
}
function setFrameHeight(height) {
sendMessageToStreamlitClient("streamlit:setFrameHeight", {height});
}
const viewer = new IfcViewerAPI({container: document.getElementById('viewer-container'), backgroundColor: new Color(0xffffff)});
viewer.axes.setAxes();
viewer.grid.setGrid();
async function loadIfc(url) {
const model = await viewer.IFC.loadIfcUrl(url);
await viewer.shadowDropper.renderShadow(model.modelID);
viewer.context.renderer.postProduction.active = true;
}
function onDataFromPython(event) {
if (event.data.type !== "streamlit:render") return;
const url = event.data.args.url;
if(url){
loadIfc(url);
}
}
// Hook things up!
window.addEventListener("message", onDataFromPython);
init();
// Hack to autoset the iframe height.
window.addEventListener("load", function() {
window.setTimeout(function() {
setFrameHeight(document.documentElement.clientHeight)
}, 0);
});
According to console my model is being opened (parsing usinf IFC4 Schema) but no IFCjs viewer is being displayed inside streamlit. I have tested the viewer running it independently in Live Server and it is fine. It appears that the last function:
Is not loading correctly. I can get the viewer to appear only if I provide hard coded height in setFrameHeight, e.g. setFrameHeight(300), but I cannot figure out how to autoset iframe height.
Hi Felipe,
thanks for the link. IFC-101 is an amazing tutorial, I know this by heart now
This works perfectly for a localhost application but not for StreamlitCloud deployment. Also the use of an ArrayBuffer means you have to use web-ifc-three instead of web-ifc-viewer, which is adding a lot of unnecessary work. With the URL solution you have the full power of IFCjs at your finger tips.
In the meantime I have just set the frame height manually and all is working great, the URL gets passed as intended. Also a little hint - the IFCs I am using are now located on Google Cloud Storage, which can generate URLs, this makes it much easier to pass them between streamlit and the IFCjs viewer.
Thanks for stopping by! We use cookies to help us understand how you interact with our website.
By clicking “Accept all”, you consent to our use of cookies. For more information, please see our privacy policy.
Cookie settings
Strictly necessary cookies
These cookies are necessary for the website to function and cannot be switched off. They are usually only set in response to actions made by you which amount to a request for services, such as setting your privacy preferences, logging in or filling in forms.
Performance cookies
These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us understand how visitors move around the site and which pages are most frequently visited.
Functional cookies
These cookies are used to record your choices and settings, maintain your preferences over time and recognize you when you return to our website. These cookies help us to personalize our content for you and remember your preferences.
Targeting cookies
These cookies may be deployed to our site by our advertising partners to build a profile of your interest and provide you with content that is relevant to you, including showing you relevant ads on other websites.