Easiest way to add button to a page which toggles visibility in the embedded viewer?

Hey @jonathon, I thought I’d join the party here :slight_smile:

To reverse the question: what would be the easiest way to create an html button which toggles visibility of layers in an embedded speckle viewer?

Essentially, recreating the functionality of the eyeball icon here:


Are we still talking Streamlit and embedded viewer here?

Nope. Whatever the easiest approach is. Let’s start with a clean slate.

I’ll state some assumptions.

  • A shallow nested Model, as per your example
  • A page implementing the Viewer from speckle-server

At its most basic, there would be a one-to-one mapping between the Enumerables of Buttons and Objects.

Let’s say you have a map of all objects in a view with a hidden state for each. This is a flat list if ObjectIds.

The click event for the button would:

  • toggle the hidden state of the corresponding object on or off
  • parse your hidden object map and return a list of all hidden object ids and objects ids of descendants of hidden objects
  • instruct the viewer to hide this list of objects

I didn’t quite understand this, I,m sure you don’t mean embedded right? do you mean implementation of one’s own Speckle server(Speckle Server | DigitalOcean Marketplace 1-Click App) or something else.

Does it need to have all the parents and Children Ids, right?

And the last question is how this can be done? :slight_smile: if there is a sample code somewhere I can take a look into it.

The viewer package is within the speckle-server repo but can be installed from npm independently.

If you also use the ObjectLoader package, there are tools in that to do that traversal for you (also with specklepy, incidentally)

To implement the Viewer (which can work with freely hosted models from speckle.xyz), look at the Sandbox-Viewer project - this is what we use to test the integration of the packages and also test some of the functionality. It does bring viewer-specific UI to it.

Instead of that, there is also a minimal example over in our Speckle Examples repo.

Again, no UI to hide and show elements, but easy to build around.

Mor Viewer specific docs here: Notion – The all-in-one workspace for your notes, tasks, wikis, and databases.


@jonathon! The sandbox-Viewer project is a nice example for what I need. Thanks!

1 Like

@jonathon! Just want to update you on the progress on this topic real quick. It’s quite nice playing around with the viewer.

P.S: Also have been thinking about how it could break the UI class into React modules. :thinking: I’ve seen a few threads about this also here and there - but anyway it’s extremely cool to have them in JS.


@jonathon thanks for your pointers so far! As you can tell from Ashkan’s post, we’ve been able to get an MVP up & running. But appetite comes with eating and we’d like to push it further. Any ideas on how we could embed animations in the viewer? Think an animated FBX with wind study results, which we could display in this context.

@dimitrie if this is not doable yet, I’d like to make an official feature request :slight_smile:

1 Like

Ideally we’d have animated Speckle Objects. Check out this random example from three.js:

Or this fun one from Sketchfab:

We’d like to bake an animation to an object (one frame == one position), save it as .FBX, alembic, USD or whatever and have it sent directly to a Speckle stream.

For our specific example, we’d like to run wind simulations in an offline package, bake the results to an animation and display these interactively in the viewer. Users would then only control the playback speed, not run the actual sim in the viewer. But if we’re thinking big, real-time physics should be the end goal :wink:


@jonathon, thanks again for your help on this one! Here is a short progress update:


UrbanDecarb is a Rhino-based app which we’re developing to quantify the CO2 footprint of various design ideas on district and city scales. Speckle helps us in separating scenarios into individual streams and presenting these interactively to wider audiences.

For the above example, we’re still in the middle of an urban planning competition for the city of Odense in Denmark hence can’t show any of the 3 design proposals publicly. We can, however, visualize the CO2 footprint of the existing infrastructure, which you see now under the above link.

There is a private version of the app, where we can switch between scenarios and compare them. Works super cool! Massive credits to @ashdotio for making it happen!

While reloading heavy models like this one, an annoying lag occurs. Is there a way to cache the streams locally somehow?


We are caching the data in local storage, but when you load and unload data the conversions need to run again and the scene tree is rebuilt.

It’s tough usually to create the best user experience while maintaining realistic expectations when dealing with large models. What I would try to do and see if it behaves better is to load all options and switch the “swapping” behaviour to just hiding all the ones not currently active. To do so, you can use the root object id’s to pass in the hide objects method with include descendants set to true [0].

Alternatively, you can load versions as they are swapped, and then when switching, hiding them rather than fully unloading them.

The tradeoff will be a larger initial loading time and higher memory consumption (mobile devices might suffer), but no lag on switching.

PS: the app looks absolutely fabulous, even in the “light version” :heart_eyes:

[0] @alex we’d probably enjoy adding a “hide/show root tree” method, but tbd re the whole filtering api efficiencies, etc.




Thanks for the tip! We’ll test it out and report with feedback, I can imagine that there is some sort of OnLoad event we could subscribe to and have a Loading… widget displayed while all data is fetched and processed for the first time. The UX would be nice - users would wait only for the first call and the subsequent ones would be instantaneous.

Yep, there is! If loading multiple versions at the same time, you’ll receive multiple load progress events, and you’ll need to centralise them in one place to display a realistic progress bar. The lazy way is to subscribe to viewer busy events and just display an indeterminate progress bar (I’m a big fan of lazy).

Another thought that came to mind is to combine all versions in one commit, and have the version swapping operate on individual versions. If you’re using grasshopper, this can be done quite elegantly (e.g., create a base object for each version). This way would be the most streamlined regarding loading times.

It’s a really cool app - might’ve said this already :smiley: We’re standing by if you and @ashdotio need more help - happy to look at code together!