Although it is true that we use lessons learned in school every day of our lives, I love it when I get to use some fundamental mathematical formula in my work.
When developing the Bipsync web app’s collaboration features we needed to clearly link up comments to the text of the note against which they had been made.
Here’s a mockup from our UX team to illustrate what we were trying to achieve:
So there were two main challenges here. First we needed to ensure that we drew the lines efficiently. Secondly we needed to keep everything in sync as the panels are scrolled and resized, so the lines pointed to the right things.
Drawing a line between any two points
Looking at the design we can see that each inline comment is associated with two separate lines. One is horizontal within the note body, with the other at an arbitrary angle connecting to the comment on the right hand side. For this, I have chosen to draw an element which is a 1px tall div of variable length which we can position using CSS. Given we know the x and y positions for the start and end of the line, we next need to calculate the length of the line to fit between these 2 points. Using a function called drawLine, into which we pass the x and y positions, we attempt to draw a line like this:
To calculate the length that this line needs to be we can work out the length of the x and y axis, and use Pythagoras’ classic theorem:
In code, this would look something like:
Simple, the value of our side is the square root of the sum of the square of the other 2 sides…
Now we have the length, we need to work out how much we need to rotate this by. This is where we use that other fun formula drilled into us from school, SOHCAHTOA.
I choose to use the end of this mnemonic, TOA. The Tangent of the angle I need to know equals the opposite of the angle, y, divided by the adjacent side, x. We actually need the inverse of this, so we will use the arctangent to get the value. If you prefer to work in degrees note that the result of this is in radians, although CSS rotates should work with either. A finished function to calculate these lines, and draw them on the body of the page might look like this:
Voila – we have the ability to place any line on the screen using this tidy function. I have used jQuery here for simplicity but there is no need to if you prefer to work without it.
Using this, you can find your x and y coordinates using something like getBoundingClientRect() or using jQuery offset() functions.
Here’s the final result:
Alternative Methods
Another approach we tried used SVG to draw the lines between the 2 points, but it’s possible to end up with large invisible boxes on the screen which can interfere with the click areas on the page – a square SVG drawing a diagonal line has a footprint for the whole x and y lengths. Drawing an entire page of div lines seemed to render slightly faster than SVG lines, according to Chrome’s analysis:
For the div approach:
And for the SVG approach:
SVG might be a better option if you are having compatibility issues with CSS transforms, but I dont think there is a huge amount in it.
From here it’s a case of of repositioning the lines as the user scrolls, which I won’t go in to. The end result is quite smooth and provides clarity when trying to make sense of a heavily annotated document:
I wanted to share the simple school math behind such a pleasing feature. It always makes me excited when I get a chance to use some of those basic concepts we had to study a long time ago, and I hope this helps others who might have a similar problem to solve.