3/08/2016

Custom interactive CSS/HTML tooltips with ggplot, shiny and R (ggvis like).


Working on data set visualization with R and shiny for Facebook data insights, we've faced a serious problem with some, one would say "simple feature".

"Hovering on plot data, shall display popover (tooltip) with the user picture, active link, short description and some other data".

First we've tried ggvis library. It was very promising and the tooltips worked like a charm.
However, very soon we've found out that library is not mature enough and leads to problems with plot interactions i.e.  zooming - to get rid of marque artifacts we would have to patch the library with some custom JS and other "fixes". This way looked "quick and dirty" so we've decided to explore the possibilities of well known and mature ggplot. If it's possible to display the data we need in "panel", let's fetch the panel with needed HTML data and play with it's position and look. The final solution is as follows:

Tooltips are managed by combination of shiny+ggplot hover functionality and CSS styles.
By setting hover argument of 'plotOutput' we can access  hover data from the server side, as an ordinary input.

Hover input is a list with:
  • position of cursor ON the image; 
  • domain - that is values of variables at the plotting area edges; 
  • range - that is position of plotting area edges in pixels relative to whole image element.

Additionally for ggplot mappings are returned.

To create tooltip first we need to identify position of the cursor inside the image element. We do it by calculating distances from left and top edge of image element from hover data. Then we create tooltip, in this app it is 'wellPanel' with required informations inside, and 'position' property set  to 'absolute' and set 'left' and 'top' properties to calculated values.

However, 'absolute' position is defined as relative to the nearest positioned ancestor. Because we want to position tooltip inside the image, we need to put both 'plotOutput' with image and 'uiOutput' with tooltip content inside additional 'div' element with 'position' property set to 'relative'.

We don't set top, left etc. for this element, so the actual position of the image doesn't change - it's edges are identical as previously, so we can use 'div' (for positioning tooltip) as substitute for image.

You can find full, working, simplified code snippet here: https://gitlab.com/snippets/16220

Special thanks to Bartek Chroł for help with developing this idea!!

ggplot with fully customised tooltip