2012-10-16 11 views
21

Jestem nowicjuszem D3.js i uczę się grać z danymi.D3.js powiązanie obiektu z danymi i dołączanie do każdego klucza

Powiedzmy mam obiektu z nazwami jak klucze, a każdy klucz ma tablicę liczb takiego:

var userdata = { 
    'John' : [0, 1, 3, 9, 8, 7], 
    'Harry': [0, 10, 7, 1, 1, 11], 
    'Steve': [3, 1, 4, 4, 4, 17], 
    'Adam' : [4, 77, 2, 13, 11, 13] 
}; 

dla każdego użytkownika, chciałbym dołączyć obiekt SVG, a następnie wykreślić linię z tablicą wartości dla tego użytkownika.

Oto moje założenie, jak to wyglądałoby w oparciu o samouczki, ale wiem, że jest niepoprawny. Ma to na celu pokazać moją ograniczoną wiedzę i daje lepsze zrozumienie tego, co robię:

Najpierw należy utworzyć linię

var line = d3.svg.line().interpolate('basis'); 

Następnie chcę powiązać dane do mojego ciała i dołączyć element svg dla każdego klucza:

d3.select('body') 
    .selectAll('svg') 
    .data(userdata) 
    .enter() 
    .append('svg') 
    .append(line) 
    .x(function(d, i) { return i; }) 
    .y(function(d) { return d[i]; }); 

Więc jestem blisko?

Odpowiedz

31

Oto kolejny przykład podobny do mbeasley: http://jsfiddle.net/2N2rt/15/, który dodaje oś, kolory i odwraca wykres prawą stroną do góry. Najpierw trochę zmasowałem twoje dane. Działa najlepiej, jeśli masz szereg wartości i użyłem klawiszy, aby ułatwić uzyskanie dostępu do właściwości name i values.

var data = [ 
    {name: 'John', values: [0,1,3,9, 8, 7]}, 
    {name: 'Harry', values: [0, 10, 7, 1, 1, 11]}, 
    {name: 'Steve', values: [3, 1, 4, 4, 4, 17]}, 
    {name: 'Adam', values: [4, 77, 2, 13, 11, 13]} 
]; 

Generalnie w d3 skonfigurowaniu takiego wykresu, który określa wielkość rzeczywistego wykresu i okoliczne marże.

var margin = {top: 20, right: 80, bottom: 30, left: 50}, 
    width = 640 - margin.left - margin.right, 
    height = 380 - margin.top - margin.bottom; 

Następnie można tworzyć skale na podstawie danych. Chociaż nie musisz ich tworzyć, znacznie ułatwiają one pozycjonowanie elementów na wykresie, konwertując wartości do punktów. Wartość domain to wartości min i maks., Które mają dane, a wartość range to wartości minimalne i maksymalne rozmiaru wykresu. Zauważ, że range dla y axis zostaje odwrócone, co powoduje umieszczenie (0,0) w lewym dolnym rogu (zwykle 0 dla osi Y na górze).

var x = d3.scale.linear() 
    .domain([0, d3.max(data, function(d) { return d.values.length - 1; })]) 
    .range([0, width]); 

var y = d3.scale.linear() 
    .domain([d3.min(data, function(d) { return d3.min(d.values); }), 
      d3.max(data, function(d) { return d3.max(d.values); })]) 
    .range([height, 0]); 

d3 ma kilka funkcji do automatycznego tworzenia skal kolorów dla Ciebie. Po prostu ustaw go za pomocą klawiszy, których chcesz użyć i liczby kolorów (myślę, że jest 10 i 20 opcji kolorów).

var color = d3.scale.category10() 
    .domain(d3.keys(data[0]).filter(function(key) { return key === "name"; })); 

Tutaj używamy naszych wag do ustawiania osi x i y. Istnieje wiele różnych opcji dla osi. TickFormat jest przydatny, aby zmienić wygląd tyknięć, d3.format ma wiele różnych opcji, więc rzadko trzeba utworzyć niestandardowy formatyzator.

var xAxis = d3.svg.axis() 
    .scale(x) 
    .tickFormat(d3.format('d')) 
    .orient("bottom"); 

var yAxis = d3.svg.axis() 
    .scale(y) 
    .orient("left"); 

Tutaj tworzymy funkcję wielokrotnego użytku, która wie, jak narysować linię. Przekażemy każdy punkt danych dla każdej osoby do funkcji linii później. Zauważ, że d przechowuje bieżący zestaw wartości, które są na wykresie, a i jest indeksem bieżących wartości w naszej oryginalnej tablicy danych.

var line = d3.svg.line() 
    .interpolate("basis") 
    .x(function(d, i) { return x(i); }) 
    .y(function(d, i) { return y(d); }); 

Wreszcie możemy zacząć dodawać rzeczy do naszej tabeli, pierwszy tworzeniu i pozycjonowaniu główny element SVG.

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

Następnie dołączanie każdej osi.

svg.append("g") 
     .attr("class", "x axis") 
     .attr("transform", "translate(0," + height + ")") 
     .call(xAxis); 

    svg.append("g") 
     .attr("class", "y axis") 
     .call(yAxis); 

dodajemy grupę (g) dla każdej osoby i powiązać dane z grupą. Będziemy korzystać z tych danych podczas rysowania linii. Zapewniamy class, abyśmy mogli później narysować wykres, jeśli chcemy.

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

Następnie w końcu narysuj linie dla każdej osoby.

people.append("path") 
     .attr("class", "line") 
     .attr("d", function(d) { return line(d.values); }) 
     .style("stroke", function(d) { return color(d.name); }); 

Użyłem twoich danych, aby odpowiedzieć na inne pytanie dotyczące rysowania siatki, gdy masz ujemne wartości. Możesz zobaczyć ten wykres na http://jsfiddle.net/2y3er/2/.

+0

To jest całkiem doskonały przykład, biorąc generyczne generowanie linii, które miałem w moim przykładzie, trochę dalej, aby stworzyć w pełni stylizowany wykres. Dobra robota! – mbeasley

+0

Jedną z rzeczy, którą zauważyłem, jest zmiana układu mojego obiektu. Zamiast tego masz tablicę 4 obiektów, podczas gdy ja mam obiekt z 4 właściwościami. Obejrzałam film krótko po zamieszczeniu tego pytania (http://vimeo.com/35005701) i mówiono o tym, że zawsze umieszczam moje dane w ten sposób. Chyba będę musiał powtórzyć, jak działa moja funkcja. – frshca

+0

Ponadto, bardzo dziękuję @Bill. Teraz odpowiedziałeś na 2 moje pytania dotyczące D3.js! Do zobaczenia wkrótce! – frshca

11

Powiedziałbym, że zmierzacie we właściwym kierunku. Oto, co chciałbym zrobić (ale wiem, że nie istnieje tylko jeden sposób, aby to zrobić):

// your user data 
var userdata = { 
    'John' : [0, 1, 3, 9, 8, 7], 
    'Harry': [0, 10, 7, 1, 1, 11], 
    'Steve': [3, 1, 4, 4, 4, 17], 
    'Adam' : [4, 77, 2, 13, 11, 13] 
}; 

// add your main SVG block 
var svg = d3.select('body') 
    .append('svg') 
    .attr('width', 400) 
    .attr('height', 200) 
    .attr('id', 'chart'); 

// add an SVG group element for each user 
var series = svg.selectAll('g.series') 
    .data(d3.keys(userdata)) 
    .enter() 
    .append('g') 
    .attr('class', 'series'); 

// create your line generator 
var line = d3.svg.line() 
    .interpolate('basis') 
    .x(function(d, i) { 
     return i*40; // *40 just to increase the chart size 
    }) 
    .y(function(d) { 
     return d*3; // *3 for the same reason 
    }); 

// add a line for each user using your SVG grouping 
var lineSVG = series.selectAll('.line') 
    .data(d3.keys(userdata)) 
    .enter() 
    .append('svg:path') 
    .attr('d', function(d) { 
     return line(userdata[d]); 
    }) 
    .attr('class','line'); 

Here's a demo powyższego kodu.

Gorąco polecam przeczytanie this article, ponieważ naprawdę pomaga w utrwaleniu sposobu działania d3.

+0

dzięki za artykuł, wygląda na to, że wiele osób poleca każdemu przeczytanie tego artykułu. – frshca