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/or height
can be delayed. Here I specify a width (foWidth
) of 300px, then find the height of the contained <div>
using getBoundingClientRect()
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 is d3.insert(el, selector)
.
Chrome doesn't create the SVG foreignObject
elements properly - they appear in the DOM as foreignobject
and can't then be selected by d3.selectAll('foreignObject')
(nor d3.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.
Modified http://d3js.org/d3.v3.min.js to a secure url
https://d3js.org/d3.v3.min.js