Just a little proof-of-concept here - using an SVG <foreignObject>
element as a container for a tooltip that can involve handy HTML features like text-wrapping and (semi-)dynamic sizing.
Gotchas so far:
-
Like an
<svg>
element, a<foreignObject>
element needs a width and a height in order to be rendered. -
However, specifying
width
and/orheight
can be delayed. Here I specify a width (foWidth
) of 300px, then find the height of the contained<div>
usinggetBoundingClientRect()
and use that to specify the height of the containing<foreignObject>
. -
If you want to provide a complex shape for the tooltip, this can be done e.g. with an SVG
<polygon>
but there's a slight paradox in needing to find the dynamic dimension of the<foreignObject>
before creating the<polygon>
, but the<polygon>
needs to appear higher than the<foreignObject>
in the SVG in order to be layered underneath it. The solution here isd3.insert(el, selector)
. -
Chrome doesn't create the SVG
foreignObject
elements properly - they appear in the DOM asforeignobject
and can't then be selected byd3.selectAll('foreignObject')
(nord3.selectAll('foreignobject')
because D3 knows about the proper names of things in the SVG XML namespace). Solution: use a class to identify all<foreignObject>
s.