Building an Interactive Dashboard With React and FabricJS
A brief effort over the three day weekend, I wanted to work on an UI project which pushed my working knowledge of FabricJS past my personal limits. I am going to talk about the design, some implementation details. There were a few pain points, so I will touch on those as well.
For those of you that are unfamiliar with Fabric JS, hopefully this will showcase some of the library's capabilities. I am really impressed with it, and look forward to using it on future projects.
After several attempts with barebones JS implementations, I decided to start the formal effort using React (Vite) and typescript, as this is where I spent a lot of my time these days. That said, the devil is in the details, as Typescript is strongly typed, and requires some additional TLC to get working.
The final product
Some background on FabricJS
After some research FabricJS came up on my radar. I have seen some impressive demos, the project has been around for over a decade,, and is actively maintained.
FabricJS is essentially a layer that abstracts you from a lot of the lower level CanvasAPI interaction. Powerful interactions are supported via an object oriented approach.
A few pain points
Documentation
There is a fair amount of documentation available out there, however as of the time of this article, it looks like a newer major version was released recently, which introduced some breaking changes. Additionally, a lot of the examples are in vanillaJS, and not typescript. This makes it a bit of a challenge to accomplish similar concepts in this stack.
Establishing the canvas
The hello world approach where you are just attempting to draw a box on a canvas was fairly straightforward. I did run into some issues when it came to canvas initialization however. The following example illustrates my approach towards initialization from within a React hook.
Loading SVG instances
My initial attempts were all vanilla JS, and really did not require a lot of effort, which established a false sense of security. Once I transitioned into the final stack I struggled with loading SVGs in a Typescript environment. After a beer or two, and five hours later, I was able to find the correction required to correctly work with a loaded SVG. For some reason, there is not a lot of discussions on the topic. Working example as follows.
fabric.loadSVGFromURL('/tank-example.svg')
.then(async (objects)=>{
if(objects){
const svg = fabric.util.groupSVGElements(objects.objects, {
id: tank.id,
top: tank.yPos,
left: tank.xPos,
lockScalingX: true,
lockScalingY: true,
hasControls: false,
opacity: .05,
hoverCursor: 'pointer'
});
....
Note that first parameter passed to the call to groupSVGElements is the result of the callback, however the 'objects' attribute needs to be passed, and not the actual attribute.
A brief background of the domain space
Basically during the manufacturing process, raw oranges are squeezed by a certain specialized machine where the content is converted to raw orange juice where it goes through a series of operations as it makes it's way along collection or 'farm' of tanks.
The dashboard approach provides operators and at a glance view of tank contents, basically a SCADA (Supervisory Control and Data Acquisition) based approach towards working with information based on physical equipment.
Designing the UI
Most examples of SCADA type systems look like they are stuck in the early 80s, and I would not be surprised if they are still working on that technology stack. I wanted to create something with greater visual appeal.
Recommended by LinkedIn
When it comes to HTML canvas, there is a lot of potential for designing graphics. I personally am a big fan of the SVG format, as we can scale without losing quality.
As for the actual sprite implementations, I decided to use Adobe Illustrator, as this fits well into my comfort zone, however any visual editor capable of exporting SVG will work.
When designing, I really encourage a disciplined approach towards naming layers, as you may need to interact with them directly at a future point.
In general, I am happy with the general look and feel, clean, minimalistic. I would love to invest another chunk of hours into UI polishing, however putting more cycles does not make a lot of sense.
Powering the UI layout
While it is possible to design a single large SVG containing all of the elements, I wanted to take a dynamic approach towards laying out the entities. This also sets me up nicely to enable a drag and drop approach towards customizing the layouts at a future point.
A JSON based format was established to model tank data. In a real world scenario, the data would be fed from APIs, however we are mocking it for demonstration purposes.
Mocking data
A component was implemented which allows the user to navigate at previous points in history, changing the state of the data. I can’t think of a real world use case for this, however I implemented this for illustration purposes.
Handling mouse over events
The cornerstone of the application is to allow a user to mouse over a given tank, which will present summary information in a modal.
Future enhancements
Really needed to timebox my efforts over the weekend, working around raising three young children. I ended up an all nighter on Saturday once my little ones dozed off. 8 hours and a few cups of coffee later, I was able to get about 90% to a finished initial version.
Although this is a POC application, I wanted to implement something that is as close to a real world application as possible, so a backlog was established consisting of the following items.
Summary
As I mentioned earlier, I am very happy with the FabricJS library at this point. The learning curve was relatively straightforward, and after a few technical glitches, I have a working blueprint.
I love this type of work as my background is a combination of both Computer Science and Visual Communications. Establishing proficiency in both areas allows me to adopt a full stack approach towards building software.
You can find more articles on my blog at https://www.matthewdalby.dev
#React #FabricJS #JavaScript #SoftwareEngineering
With over two decades of experience in software engineering, Matthew Dalby is a seasoned professional who has consistently leveraged cutting-edge technology to solve complex problems and deliver impactful solutions. Matthew is always seeking new opportunities to innovate and collaborate on forward-thinking projects. As of recently, he has placed focus on sharing his personal experience and knowledge with the larger community.