2012-12-20 29 views
17

Używam d3.js i pracuję nad wykresem obszaru pędzla, modyfikując this example. Oprócz zmiany osi X na podstawie pędzla, chciałbym, aby oś y została przerysowana na podstawie wartości y danych wchodzących w skład pędzla (podobnie do zachowania a Google Finance chart).Zaktualizuj oś y wykresu obszaru szczotkowanego

Mam funkcjonalność działającą, ale tylko w taki sposób, aby umożliwić rysowanie pędzla zarówno w przestrzeni X, jak i Y. I tak w tym poprzez dodanie skalę y zmiennej brush:

var brush = d3.svg.brush() 
    .x(x2) 
    .y(y2) 
    .on("brush", brush); 

Dzięki brush.extent() powrotu poniższa tablica wielowymiarowym: [ [x0, y0], [x1, y1] ]. I potem korzystać z tych danych w funkcji brush() przedefiniowanie X i domenę y- dla wykresu ostrości:

function brush() { 
    var extent = brush.extent(); 
    x.domain(brush.empty() ? x2.domain() : [ extent[0][0], extent[1][0] ]); 
    y.domain(brush.empty() ? y2.domain() : [ extent[0][1], extent[1][1] ]); 
    focus.select("path").attr("d", area); 
    focus.select(".x.axis").call(xAxis); 
    focus.select(".y.axis").call(yAxis); 
} 

To działa, ale przez określenie skali y w zmiennej pędzlem, użytkownik może teraz przeciągnąć ' "na wykresie ostrości", a nie tylko na przeciąganie z zachodu na wschód, jak na oryginalnym wykresie.

Zasadniczo moje pytanie brzmi: jak uzyskać zakres wartości, które mieszczą się w obszarze pędzla, a nie zakres samego obszaru pędzla? Czy to możliwe?

Dokumentacja pędzla d3 to here.

Odpowiedz

13

Wymyśliłem rozwiązanie.

Do odfiltrowania oryginalnego zestawu danych użyłem filtru X.domain z filtrem. Ten nowy przesączono zestaw danych zawiera tylko wartości, które mieszczą się w szczotki:

// Use x.domain to filter the data, then find the max and min duration of this new set, then set y.domain to that 
    x.domain(brush.empty() ? x2.domain() : brush.extent()); 
    var dataFiltered = data.filter(function(d, i) { 
    if ((d.date >= x.domain()[0]) && (d.date <= x.domain()[1])) { 
     return d.duration; 
    } 
    }) 
    y.domain([0, d3.max(dataFiltered.map(function(d) { return d.duration; }))]); 

Wreszcie, należy przerysowanie osi Y, jak również w kierunku X:

focus.select("path").attr("d", area); 
focus.select(".x.axis").call(xAxis); 
focus.select(".y.axis").call(yAxis); 
+3

Doskonała odpowiedź! Mogłem wpaść prosto w kod mojego wykresu, okrzyki. – fundead

0

krótszy możliwość byłoby użyć d3.scale.invert() na swojej brush.extent() tak:

var domainExtent = brush.extent().map(function(d){return scale.invert(d);}); 
var filteredData = data.filter(function(d){return ((d <= domainExtent[1]) && (d >= domainExtent[0]));}); 

jednak, teraz d3 zyskał d3.brushX(), który pozwala tylko na szczotkowanie w kierunku wschodnim/zachodnim według projektu.