2012-11-12 16 views
8

Używam d3 do renderowania uproszczonego wykresu Gantta, z panoramowaniem i powiększaniem za pomocą d3.behavior.zoom.Skala porządkowa panoramowania/powiększania?

Skala x to skala czasowa (nieznacznie zmodyfikowana względem środkowych dni kalendarzowych w kolumnach itd.) I działa pięknie, ale mam problem z wyborem sposobu powiększania/przesuwania skali y, której domeną jest lista zadań które często będą zbyt duże, aby zmieścić się w obszarze wykresu, a więc potrzeba panoramowania/powiększania.

Czy istnieje sposób, aby określić domyślną skalę porządkową, aby reagować na zdarzenia powiększania/pomniejszania, czy powinienem napisać niestandardową skalę? A jeśli potrzebuję napisać niestandardową skalę, lepiej byłoby oprzeć ją na d3.scale.ordinal (przechowując całą listę zadań i używając tylko widocznego podzbioru jako swojej domeny) lub na d3.scale. liniowy (a następnie zaimplementować coś podobnego do skali porządkowej dla pasm zakresu itp.?).

Czy jest coś, czego mi brakuje (całkowicie prawdopodobne, ponieważ jest to mój pierwszy projekt przy użyciu d3)?

Odpowiedz

3

Rozszerzając się nieco od poprzedniej odpowiedzi, ponieważ kontaktowałem się prywatnie z wyjaśnij, jak to zrobiłem.

Najpierw zrzut ekranu aplikacji, której zadaniem jest agregowanie i wyświetlanie danych planowania zebranych z różnych źródeł (pliki PowerPoint, korporacyjne bazy danych itp.).

screenshot

Odpowiedni bit jest prawo oś pionowa z kolorowych kropek, gdzie każda kropka reprezentuje wysiłek danego projektu i zaangażowanych organizacji. Szary obszar na osi to pędzel d3.js i można go przesuwać/zmieniać rozmiar, aby zmienić dane wykresu/tabeli w czasie rzeczywistym.

// the axis is a regular ordinal axis, with a brush 
y2 = d3.scale.ordinal(), 
brush = d3.svg.brush().y(y2).on('brush', brushReact), 
// [...] 
// brush event handler 
function brushReact() { 
    if (tasksSlice == null) 
     return; 
    var yrb = y2.rangeBand(), 
     extent = brush.extent(), 
     s0 = Math.round(extent[0]/yrb), 
     s1 = Math.round(extent[1]/yrb); 
    if (s0 == tasksSlice[0] && s1 == tasksSlice[1]) 
     return; 
    tasksSlice = [s0, s1]; 
    inner.refresh(); 
} 

Co dzieje się wewnątrz przewodnika jest dość prosta:

  • uzyskać stopień pędzla
  • transpozycji do indeksów w moim tablicy danych
  • plaster tablicę moich danych i ustawić wynik jako dane do wyświetlenia
  • odśwież tabelę i tabelę

Mam nadzieję, że to wyjaśni.

2

Okazuje się, że to nie jest takie trudne, musiałem:

  • napisać skalę niestandardową, przeważnie identyczne d3.scale.ordinal, chyba że przechowuje pełny zakres wartości domen i wdraża kawałek ([min, max]) metoda ustawiająca zakres widocznych wartości domen
  • śledź deltę tłumaczenia y w wywołaniu zwrotnym zdarzenia powiększenia i dodaj ją do zmiennej przechowującej całkowite y tłumaczenie
  • sprawdź, czy całkowita kwota tłumaczenia jest > = niż delta y między dwiema wartościami zakresu, jeśli jest to sprawdzanie, czy nie jesteśmy już w jednej z (widocznej lub niewidocznej) domeny granice (0 lub długość), a jeśli nie zwiększamy ani nie zmniejszamy indeksów fragmentów o 1, zresetuj całkowitą zmienną tłumaczącą, a następnie ponownie rysuj oś
+0

Czy możesz zamieścić opis? dzięki! – Dan

+0

+1 dla przykładowego kodu. – Thomas

+0

Byłoby naprawdę świetnie z przykładem, dzięki! – Kristoffer