git log, wstęp do D3JS

Dzisiaj więcej kodu! W końcu to blog programistyczny. W dzisiejszym wpisie pokażę jak udało mi się stworzyć wizualizację grafu commitów.

Obecnie graf wygląda tak:

Graf składa się z trzech struktur

node – pojedynczy commit, opisany przez sha, koordynaty x oraz y

link – połączenie pomiędzy dwoma commitami, składa się z identyfikatorów poszczególnych commitów oraz z identyfikatora kolumny. Kolumna to zmienna pomocnicza, przydaje się do wyznaczenia kolorów połączeń

message – dodatkowe informacje o commicie, treść commita, autor, data, identyfikator

Wstęp do d3js

D3js, framework do wizualizacji danych. Niby tyle… lub aż tyle. Możecie zobaczyć ile jest przykładów i jak niesamowicie się one prezentują tu! Naprawdę robi to wrażenie. Widać też jak potężnym narzędziem jest ta biblioteka.

Standardowo możemy sobie ją pobrać za pomocą package managera npm lub załączyć cdn.

Obecnie można się spotkać z dwoma wersjami 3 i 4. Należy na to zwrócić uwagę, ponieważ zmiany są w pewnych przypadkach dość spore i część przykładów z 3 nie będzie nam działać na wersji 4. Zdecydowałem się na wersję 3, ponieważ więcej przykładów znalazłem właśnie w tej wersji.

Bazą grafu do gita będzie element svg. Dlaczego? daje bardzo dużo możliwości, jeżeli chodzi o bardziej zaawansowane animacje czy kształty.

Ok, na początku określmy punkt startowy dla grafu:

W pliku HTML wstawiamy  tag svg, do tego elementu będziemy się odwoływać w naszych skryptach i w ramach tego tagu powstaną wszystkie inne elementy.

W pierwszej kolejności musimy „chwycić” svg przez d3js

naprawdę proste, na obiekcie d3 wywołujemy metodę select, jako jej parametr określamy na jakim elemencie chcemy pracować. W tym przypadku jest to svg, ale nic nie stoi na przeszkodzie aby zaznaczyć jakikolwiek inny tag HTML. Dodatkowo możemy zaznaczyć klasę jak i identyfikator. Dla klasy odwołujemy się poprzez ‚.nazwa_klasy’, a do identyfikatora ‚#identyfikator’.

W pierwszej kolejności wygenerujmy sobie grupy, które będą nam spajać węzły, dodatkowe informacje oraz ten szary prostokąt w tle.

  • selectAll – zaznacza nam wszystkie tagi g w obrębie elementu svg. Dodam , że tag svg jest o tyle specyficzny, że nie możemy (możemy ale nie będą widoczne) wewnątrz niego dodawać niektórych „klasycznych” tagów min. div. Odpowiednikiem div jest właśnie element g.
    Różnicą pomiędzy metodą select, a metodą selectAll , jest to, że ta druga zwraca nam wszystkie elementy w postaci tablicy.
  • data – przekazujemy tablicę commitów, tak przekazane dane będą służyć do następnych operacji.
  • enter – tworzy powiązanie pomiędzy zaznaczonymi elementami przez funkcję selectAll, a przekazanymi przez funkcję data.
  • append – funkcja tworząca elementy, w tym przypadku tagi g. Ile ich ma stworzyć, to zwraca funkcja enter. Ilość stworzonych elementów określa rozmiar tablicy przekazanej w funkcji data. Istotne jest to, że zostaną stworzone jedynie brakujące elementy. Dzięki temu ilość elementów oraz danych w tablicy zawsze jest taka sama.
  • attr – przekazujemy atrybut dla każdego elementu, tego stworzonego jak i tych istniejących.

Po tej operacji powinna powstać poniższa struktura, oczywiście na widoku na razie nie będzie nic widać, ale to jeszcze chwilka 😉

Dodajmy troszkę elementów wizualnych. Na początku szare prostokąty.

Więc, tak jak w poprzednim przykładzie, rozpoczynamy od funkcji append, która doda nam dokładnie taką samą ilość elementów rect jak g. Ustawiamy, aby prostokąt rozpoczynał się w punkcji x = 0, punkt wyznaczamy dynamicznie na podstawie danych przekazanych poprzez funkcję data.

classed – funkcja spełnia dokładnie takie samo zadanie jak .attr(„class”,’nazwa_klasy’), czyli ustawia klasę dla elementu. W tym jednak przypadku posiada jeden bardzo przydatny parametr setFlag, ustawienie go na true powoduje, że klasa ta będzie dodana do elementu. Wartość false usunie klasę z elementu.

style – oczywiście jeżeli chcemy zmienić jeden parametr wizualny naszego elementu, nie musimy specjalnie tworzyć  do tego klasy w CSS. Możemy przekazać go wprost za pomocą funkcji style. Poniżej to samo wywołanie ale z wykorzystaniem funkcji style zamiast classed:

A efektem tego jest tak ostylowany element:

Dokładnie takim samym sposobem tworzymy commity oraz informacje o commicie.

Do końca pozostały nam jedynie połączenia. Zaimplementować można to tak:

Można zauważyć że wyjściem do generacji jest svg. Jako, że połączenia są pomiędzy elementami różnych grup, to wydzieliłem je na zewnątrz. Jedyną wartą uwagi częścią jest:

W ten sposób odwołujemy się do węzła, w którym aktualnie się znajdujemy, w tym przypadku aktualizujemy wartości punktów granicznych dla linii.

Podsumowanie

Przede wszystkim należy zwrócić uwagę na fantastyczne API jakie udostępnia biblioteka. Bardzo przejrzyste, intuicyjne, naprawdę rewelacja. Tak jak pisałem w poprzednim wpisie, dokumentacja jest… ciężka i toporna, ale jest w niej wszystko. Za to istnieje mnóstwo tutoriali blogów i przykładów. Jest się z czego uczyć. W następnym wpisie postaram się opisać interakcję użytkownika z elementami, jak i również integrację d3js z VueJs.

  • Właśnie uczę się hmm gitować 🙂 Więc do tego wpisu najpewniej wrócę znowu!