Taming the UX monster with SVG: my first encounter with custom SVG connectors and how you can excel it at too!

  • I needed to make an interaction like above where user can select a node on LHS and connect with nodes on RHS.
  • There can be many-to-many relationship between these nodes.
  • User can chose to remove an existing connection.
  • All existing connections have to be plotted when page loads and auto-saved whenever user adds/remove a connection
  • The cherry on top was - filter! User can filter the nodes on LHS or RHS at anytime and the Connections have to show according to currently visible nodes
  • After sweating my fingers for few days and losing some hairs, the final outcome was like this:

Choosing the right weapon

The output looks very similar to what I needed, so I started working on achieving the requirements using D3 js. As the project was in VueJs, I also started looking for VueJs + D3Js implementations and VueJs plugins to show Tree/Relationship/Organogram etc.

There are many such libraries/plugins in D3 and Vue with nice output, but they all were limited to showing existing connections between simple Text nodes. In nutshell, they took a json object with list of nodes and their relationship with corresponding nodes. They had very limited support for Rich markup/html and user-generated events.

I needed to support inhouse component library and also quick filter on each side of nodes, to change both markup and connections between them at user’s will. Also I needed events to save the latest connection when it was added/removed by a user.

So I concluded that rather than extending an existing library and still be limited by its original design, its better to make a custom solution, solving the project-specific need and it would also be easy to scale up or modify it considering that it would not be a complex third party library.

As all these libraries use mainly SVG, I started exploring SVG and alternatives. I found following:

  • CSS3 + HTML + JS: while it may have been possible to make a solution simply using CSS and complex borders/boxes, it would have been very difficult to manipulate the styles using plenty of JS code. And hence I gave up after spending couple of hours.
  • Canvas: this could be an ultimate solution considering the powers of Canvas, but I had little exposure to it. After bit of study I built an opinion that Canvas is ultimate super-set of all interactions HTML has to offer. But it may be an overkill considering my minimal Drawing requirements, while canvas offers vast Painting solutions at cost of verbose API.
  • SVG: They are easy to learn, offers inbuilt api to draw simple lines and even really complex curves. You can create many types of nodes inside an svg element and add/remove them easily based on user events. Has lightweight api and easy on browser performance. This looked like perfect weapon!

Know thy Weapon

  • Its as easy as following to write your first SVG path.
  • You need an SVG element, with various elements like Line, Path, Archs etc inside it.
  • You must know the start and end x, y positions of the path you want to Draw.
  • The api is simple to start with but can really mess up your head after a while! So try to keep it small and manageable.
  • I ended up writing following (crux of) code to support various variables to draw a curved connector path

Useful ammo

  • Element.getBoundingClientRect()
  • Element.offsetTop
  • querySelector
  • appendChild
  • removeChild

They are really interesting to know and play around with, and it will help you realize the amazing relationship between browser Window and user’s Viewport!

Boo!

  • Simple Web APIs like childNode.remove() to self-remove an element from DOM was not supported by our long-term frenemy IE 11
  • As of writing this article in early 2021, its not possible to give Z-index to an SVG element, so if you want to plot an Active or high-priority element on newer element, wait till this gets accepted!
  • Element.offsetParent.getBoundingClientRect(): had to use PARENT container as the Checkbox will always give offsetTop = 0 as its hidden due to custom styles we used to show fancy checkboxes
  • While its possible to use Gradients to fade out a path, the gradient becomes invisible if the delta between Y coordinates is 0! And that needs special instruction as below.
  • Its possible to create really complex or pixel-perfect paths in SVG, but that would lead to some utter complex equations to be solved like below. So i would suggest to simply refrain from it and look for alternate UX rather than building a nightmare for yourself and future devs.

Keep the map handy

This will also help you understand your own code in future and write proper unit tests covering various scenarios.

Have a great time developing fantastic UX and feel free to reach me if i can offer any assistance in a similar ride!

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store