2013-04-17 13 views
16

Zaimplementowałem następujący wykres z krawędziami renderowanymi za pomocą d3.svg.diagonal(). Jednak gdy próbuję zastąpić przekątną d3.svg.line(), nie wydaje się, aby wyciągnąć dane celu i źródła. czego mi brakuje? Czy jest coś, czego nie rozumiem o d3.svg.line?D3: Zamienianie d3.svg.diagonal() na d3.svg.line()

enter image description here

Poniżej znajduje się kod mam na myśli, a następnie pełnego kodu:

var line = d3.svg.line() 
    .x(function(d) { return d.lx; }) 
    .y(function(d) { return d.ly; }); 

...

var link= svg.selectAll("path") 
    .data(links) 
    .enter().append("path") 
    .attr("d",d3.svg.diagonal()) 
    .attr("class", ".link") 
    .attr("stroke", "black") 
    .attr("stroke-width", "2px") 
    .attr("shape-rendering", "auto") 
    .attr("fill", "none"); 

Cały kod:

var margin = {top: 20, right: 20, bottom: 20, left: 20}, 
    width =1500, 
    height = 1500, 
    diameter = Math.min(width, height), 
    radius = diameter/2; 


var balloon = d3.layout.balloon() 
    .size([width, height]) 
    .value(function(d) { return d.size; }) 
    .gap(50)     

var line = d3.svg.line() 
    .x(function(d) { return d.lx; }) 
    .y(function(d) { return d.ly; }); 


var svg = d3.select("body").append("svg") 
    .attr("width", width + margin.left + margin.right) 
    .attr("height", height + margin.top + margin.bottom) 
    .append("g") 
    .attr("transform", "translate(" + (margin.left + radius) + "," + (margin.top + radius) + ")") 

    root = "flare.json"; 
    root.y0 = height/2; 
    root.x0 = width/2; 

d3.json("flare.json", function(root) { 
    var nodes = balloon.nodes(root), 
     links = balloon.links(nodes); 


var link= svg.selectAll("path") 
    .data(links) 
    .enter().append("path") 
    .attr("d",d3.svg.diagonal()) 
    .attr("class", ".link") 
    .attr("stroke", "black") 
    .attr("stroke-width", "2px") 
    .attr("shape-rendering", "auto") 
    .attr("fill", "none"); 

    var node = svg.selectAll("g.node") 
    .data(nodes) 
    .enter() 
    .append("g") 
    .attr("class", "node"); 

    node.append("circle") 
     .attr("r", function(d) { return d.r; }) 
     .attr("cx", function(d) { return d.x; }) 
     .attr("cy", function(d) { return d.y; }); 

    node.append("text") 
     .attr("dx", function(d) { return d.x }) 
     .attr("dy", function(d) { return d.y }) 
     .attr("font-size", "5px") 
     .attr("fill", "white") 
     .style("text-anchor", function(d) { return d.children ? "middle" : "middle"; }) 
     .text(function(d) { return d.name; }) 
}); 

Porównanie sposobu, w jaki atrybut d svg znika przy użyciu "linii". enter image description here enter image description here

+0

Ty nie wydają się być za pomocą 'line' nigdzie w kod. Atrybut 'd' ścieżki nadal jest ustawiany przy użyciu' d3.svg.diagonal'. –

+0

Tak, ale gdy podstawię "linia" dla "d3.svg.diagonal()" 0, łamie vis. Nie mogę zrozumieć dlaczego. –

+0

Jak to się psuje? –

Odpowiedz

1

Wystarczy ustawić atrybut linku d linii:

.attr("d", line) 
+0

Tak, ale gdy zastępuję "wiersz" dla "d3.svg.diagonal()" 0, łamie ono vis. –

+0

Czy możesz utworzyć mały przykład na jsFiddle? –

+0

Próbowałem, ale kod źródłowy z układem balonu jest na githubie i wydaje się, że go nie akceptuje. –

1

miałem ten sam problem ... Jest jsFiddle here.

Należy pamiętać, że zmiana line na diagonal spowoduje jego działanie.

+0

Moja sugestia to umieszczenie kodu z jsFiddle tutaj, ponieważ nie zawsze jest niezawodny i nieaktualny. W takim przypadku odpowiednia odpowiedź będzie dostępna w tej odpowiedzi bez konieczności wchodzenia na zewnętrzną stronę internetową. – Taryn

+1

@mobeets Musisz podać poprawne wejście do 'line()'. Możesz to zrobić owijając 'line()' na innej funkcji, polecając @ elusive-code lub zwracając 'line()' poprawne wartości wejściowe, które możesz zobaczyć na [moim modie twojego skrzypiec] (http: // jsfiddle. net/qsEbd/213 /). – jkutianski

2

Może enkapsulacji funkcję przekątnej i edycji jego parametrów może pracować dla Ciebie:

var diagonal = d3.svg.diagonal(); 
var new_diagonal = function (obj, a, b) { 
    //Here you may change the reference a bit. 
    var nobj = { 
     source : { 
      x: obj.source.x, 
      y: obj.source.y 
     }, 
     target : { 
      x: obj.target.x, 
      y: obj.target.y 
     } 
    } 
    return diagonal.apply(this, [nobj, a, b]); 
} 
var link= svg.selectAll("path") 
    .data(links) 
    .enter().append("path") 
    .attr("d",new_diagonal) 
    .attr("class", ".link") 
    .attr("stroke", "black") 
    .attr("stroke-width", "2px") 
    .attr("shape-rendering", "auto") 
    .attr("fill", "none"); 
21

Pytanie jest dość stary, ale ponieważ nie widzę odpowiedzi, a ktoś może napotkać ten sam problem, to jest tutaj .

Powodem prosta wymiana przekątnej z linii nie działa dlatego d3.svg.line i d3.svg.diagonal zwracać różne wyniki:

  • D3. svg.diagonal zwraca funkcję, która akceptuje dane i jej indeks i przekształca ją w ścieżkę przy użyciu projekcji. Innymi słowy: diagonal.projection określa, w jaki sposób funkcja otrzyma współrzędne punktów z dostarczonej bazy danych.
  • d3.svg.line zwraca funkcję, która akceptuje tablicę punktów linii i przekształca ją w ścieżkę. Metody line.x i line.y określić jak współrzędne punktu retreived z jednolitego elementu dołączonego tablicy

D3 SVG-Shapes reference

SVG Paths and D3.js

Więc nie można używać wyniku d3.svg.linia bezpośrednio w selekcji d3 (przynajmniej wtedy, gdy chcesz narysować wiele linii).

trzeba zawinąć go w innej funkcji tak:

var line = d3.svg.line() 
       .x(function(point) { return point.lx; }) 
       .y(function(point) { return point.ly; }); 

function lineData(d){ 
    // i'm assuming here that supplied datum 
    // is a link between 'source' and 'target' 
    var points = [ 
     {lx: d.source.x, ly: d.source.y}, 
     {lx: d.target.x, ly: d.target.y} 
    ]; 
    return line(points); 
} 

// usage: 
var link= svg.selectAll("path") 
    .data(links) 
    .enter().append("path") 
    .attr("d",lineData) 
    .attr("class", ".link") 
    .attr("stroke", "black") 
    .attr("stroke-width", "2px") 
    .attr("shape-rendering", "auto") 
    .attr("fill", "none"); 

Tutaj jest wersja jsFiddle pracy mobeets napisali: jsFiddle

+1

Myślę, że '.attr (" d ", funkcja (d) {linia powrotu ([{lx: d.target.x, ly: d.target.y}, {lx: d.source.x, ly : d.source.y}]);}); ' to lepszy sposób na zrobienie tego zamiast owijania' line() 'w funkcji globalnej. – jkutianski

+0

Dodatkowe punkty za zastąpienie "przekątnej" w tym kontekście, nieuchwytnym kodem, zamiast dostarczania alternatywnego rozwiązania. Minęło ponad półtora roku, a jak powiedziałeś, "ktoś może stanąć przed tym samym problemem" (ja). Nie znalazłem tego rozwiązania w tak prostej formie nigdzie indziej i na pewno jest wielu ludzi, którzy tego chcą. – Mars