Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sizing of SVG foreignObject element to fit HTML element

Tags:

html

svg

size

d3.js

I am making a visualization using the D3 javascript library. I would like to create tooltips for some of the elements of the visualization and and my client wants them to look like a 'paper snippets/post-its'. Initially I created plain DIV's for the tooltips using some nice CSS tricks to create the desired appearance. (inspired by this tutorial)

I would like to use encapsulate the tooltips into the SVG foreignObject-element so its better fits to the visualization and I can manipulate them easily. (e.g. zooming/panning) So my question is : how to get the proper size of the DIV, which lies inside the foreignObject-element, so I can set the size of the foreignObject-element accurately ? Especially when using margin/padding/shadow ....

I figured it out by using .getBoundingClientRect() but I do not know if this is the best way.

Here is a code-example :

var body = d3.select("body");

var svg = body.append("svg");

var tooltipContainer = svg.append("svg:g");

var html = tooltipContainer.append("foreignObject")
var div = html.append("xhtml:div")
    .attr('class', 'paper-tooltip')
    .html("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec eu enim quam.     Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec eu enim quam. Lorem ipsum     dolor sit amet, consectetur adipiscing elit. Donec eu enim quam. Lorem ipsum dolor sit amet,     consectetur adipiscing elit. Donec eu enim quam. ");

var bcr = div[0][0].getBoundingClientRect();

html.attr('x', 50)
    .attr('y', 50)
    .attr('width', bcr.width)
    .attr('height', bcr.height);

svg.call(d3.behavior.zoom().on('zoom', redrawOnZoom));

 function redrawOnZoom(){
    tooltipContainer.attr('transform', 'translate(' + d3.event.translate + ')' + ' scale(' +         d3.event.scale + ')');
};

Here is a working jsFiddle example : http://jsfiddle.net/jhe8Y/1/

EDIT:

I realized, that for different shadow-box settings the .getBoundingClientRect() will not work. i also realized that with my first solution the .getBoundingClientRect() returns too-large size, especially on the right size.

So I tried another way by using the jQuerys .outerWidth(true)/.outerHeight(true) and computing the shadow size manually. This seems to work fine, but it feels just terribly to do something like that.

Is there any other way how to get the exact size of a DIV with all it's components ?

Updated jsFiddle is here : http://jsfiddle.net/jhe8Y/3/

like image 424
karlitos Avatar asked Aug 20 '13 14:08

karlitos


Video Answer


1 Answers

You don't need to scale it up and down. There is no real use of it, right? Then you can set both foreignObject height and width to 1, and via CSS set foreignObject { overflow: visible; }.

like image 193
mahish Avatar answered Sep 17 '22 15:09

mahish