2015-01-31 7 views
5

Ich möchte eine foreign object einfügen, wenn Menschen auf einen Kreis zoomen. Ich weiß, es ist ein Insert before:Wie füge ich nach einem Geschwisterelement in d3.js ein

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) 

} 

aber die HTML-Inhalte würden von dem geklickten Kreis verdeckt werden. Gibt es eine insert after a specific sibling, so dass das ForeignObject danach eingefügt werden würde?

Stören Sie Robert Longsons Antwort nicht. Er nahm nur etwas, was er in dem Dokument gelesen hatte, ohne zu beweisen, dass es funktioniert.

@ 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(); 
+0

Warum nicht 'append'? – benjaminz

Antwort

1

Sie insert verwenden können, um den Inhalt vor jedem anderen gleichrangigen Elemente einzufügen, das bestehende Geschwisterelement ist das zweite Argument der insert-Methode.

Wenn Sie nach Element x einfügen möchten, müssen Sie einen Selektor erstellen, der das Element unmittelbar nach x zurückgibt.

Wenn Sie nach allen vorhandenen Geschwister einfügen möchten, verwenden Sie append.

Zwischen diesen beiden Methoden können Sie überall einfügen.

+0

Verwenden Sie das zweite Argument, um das Element nach diesem Element einzufügen. –

7

Sie können css "Element + Element" Selektor (direct adjacent combinator) verwenden. Angenommen, Sie müssen Element einfügen „zweite“ direkt nach dem Element „erste“:

d3.select('body') 
    .insert('div', '#first + *') 
    .attr('id', 'second'); 
+0

Ich dachte nicht, dass dies in dem Fall funktionieren würde, wenn nach dem '# first' kein Element vorhanden ist, aber es funktioniert, weil als [docs] (https://github.com/d3/d3-3. x-api-reference/blob/master/Selections.md # einfügen) erklären, wenn der Selektor nicht mit irgendeinem Element übereinstimmt, wird das 'insert' als' append' behandelt. Also ja, danke! – artfulrobot