In this recent post we looked at a new 2D heatmap capability that we’ve added to Project Dasher. In this post we look at what was needed to make this heatmap resizable – but with a fixed aspect ratio – as well as being movable and displayed with a transparent background.
Luckily, this previous post shows how to create a transparent, movable window – which we already use to show our surface shading legend – so we were able to use that as a basis for today’s implementation.
Firstly, let’s take a look at it working. Note the fact the window is basically invisible unless hovered over, at which point we see a shadow effect at its border.
So there are two main features we wanted to add: the ability to maintain the panel’s aspect ratio (which in this case is 1, as we want it to be square) and the ability for the user to resize it (while keeping it square :-).
Let’s start with the second one… in this case I went ahead and modified the TransparentDockingPanel class to have an option that specifies that we want the panel to be resizable. Here’s the modified class (in TypeScript, as is usual for this project), which – when initialized – checks the options.resize flag, and if it’s set we create the footer that’s needed to resize the panel:
I’ve gone ahead and added additional options for creating a title and a close button: while we’re not going to use these now, at some point it’s likely we’ll want to add multiple heatmaps – and make it easy for the user to dismiss them – so having a close button and a descriptive label for each could well prove useful.
In case you’re wondering, the footer (and title/close button) creation code is simply taken from the initialization code for the Autodesk.Viewing.UI.DockingPanel class. The main difference in our class is that these become options rather than standard behaviour.
The other piece – to keep the panel square – we do from the child ResizableDockingPanel class. This contains a MutationObserver to keep an eye on the panel’s style, and checks for when the width and height are modified. During the onResize() event we take the minimum of the width and height – and use that as the value for both, assuming it isn’t below a minimum threshold – and then set that back on the panel but also use it to resize the panel contents (in this case our heatmap).
Note that we can’t set the _resizeContents member during the constructor of any base class – super() calls can’t use the ‘this’ keyword – so we have a separate property set to properly create one of these panels.
Here’s how we’re using this class inside Dasher:
Here’s the CSS that manages the shadow effect shown on-hover as well as changing the resizer and close button icons from light to dark:
The feature works quite well. Here’s a longer animation showing the new panel but also cycling through different types of sensor data:
If you want to play around with this yourself, here’s a link.
Thinking about where this feature could go in the future: the same mechanism could easily be used to display multiple heatmaps concurrently, which would allow us to compare and contrast different sensor feeds and even simulation results. This would take a bit more UX work, to establish how best to choose the sensor type per heatmap (etc.), but it should provide some interesting analysis capabilities.