I want to insert a foreign object
when people zoom in on a circle. I know there is a Insert before
:
function zoom(d, i) {
d3.select("g").insert("foreignObject",'#'+d.name) // insert after a circle in the group
.attr("width",450)
.attr("height",450)
.attr("id",'f_'+d.name)
.append("xhtml:div")
.html(content)
}
but the html content would be obscured by the clicked circle. Is there a insert after a specific sibling
so that the foreignObject would be inserted after it?
Don't bother Robert Longson's answer. He just took something he read in the document without proving that works.
@ Code:
var w = 1280,
h = 800,
r = 720,
x = d3.scale.linear().range([0, r]),
y = d3.scale.linear().range([0, r]),
node,
root;
var pack = d3.layout.pack()
.size([r, r])
.value(function(d) { return d.size; })
var vis = d3.select("body").insert("svg:svg", "h2")
.attr("width", w)
.attr("height", h)
.append("svg:g")
.attr("transform", "translate(" + (w - r) / 2 + "," + (h - r) / 2 + ")");
node = root = data;
console.log(node)
var nodes = pack.nodes(root);
vis.selectAll("circle")
.data(nodes)
.enter().append("svg:circle")
.attr("class", function(d) { return d.children ? "parent" : "child"; })
.attr("id",function(d){ return d.name; })
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.attr("r", function(d) { return d.r; })
.on("click", function(d) { return zoom(node == d ? root : d); });
vis.selectAll("text")
.data(nodes)
.enter().append("svg:text")
.attr("class", function(d) { return d.children ? "parent" : "child"; })
.attr("x", function(d) { return d.x; })
.attr("y", function(d) { return d.y; })
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.style("opacity", function(d) { return d.r > 20 ? 1 : 0; })
.text(function(d) { return d.name; });
d3.select(window).on("click", function() { zoom(root); });
function zoom(d, i) {
console.log(d)
var k = r / d.r / 2;
x.domain([d.x - d.r, d.x + d.r]);
y.domain([d.y - d.r, d.y + d.r]);
var t = vis.transition()
.duration(d3.event.altKey ? 7500 : 750);
t.selectAll("circle")
.attr("cx", function(d) { return x(d.x); })
.attr("cy", function(d) { return y(d.y); })
.attr("r", function(d) { return k * d.r; });
t.selectAll("text")
.attr("x", function(d) { return x(d.x); })
.attr("y", function(d) { return y(d.y); })
.style("opacity", function(d) { return k * d.r > 20 ? 1 : 0; });
if(!d.children)
{
if(!$('#f_'+d.name).length){
d3.select("g").insert("foreignObject",'#'+d.name)
.attr("width",450)
.attr("height",450)
.attr("id",'f_'+d.name)
.append("xhtml:div")
.html('<img src="https://www.gravatar.com/avatar/60163c0083f4d2a54de2bb079a7211f8?s=128&d=identicon&r=PG&f=1">')
}
}
else
{
$("foreignObject").attr("opacity",0);
}
node = d;
d3.event.stopPropagation();
You can use css "element+element" selector (direct adjacent combinator). Let's say you need to insert element "second" right after element "first":
d3.select('body')
.insert('div', '#first + *')
.attr('id', 'second');
You can use insert to insert the content before any other sibling element, the existing sibling element is the second argument to the insert method.
If you want to insert after element x, you'll need to create a selector that returns the element immediately after x.
If you want to insert after all existing siblings then use append.
Between those two methods you can insert anywhere.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With