D3 üçün incə bir giriş: Yenidən istifadə edilə bilən baloncuk qrafikini necə etmək olar

D3 ilə başlayın

D3 öyrənməyə başlayanda mənə heç bir məna vermədi. İşlər yenidən istifadə edilə bilən diaqramlarla məşğul olmağa başladıqda daha aydın oldu.

Bu yazıda sizə D3-ə incə bir təqdimat verərkən təkrar istifadə edilə bilən baloncuklar cədvəlini necə yaratacağınızı göstərəcəyəm. İstifadə etdiyimiz məlumatlar, 2017-ci ilin yanvar ayında freeCodeCamp-da yayımlanan hekayələrdən ibarətdir.

Bu, yaratacağınız diaqramdır

D3 haqqında

D3, məlumatların vizuallaşdırılması üçün JavaScript kitabxanasıdır. HTML, SVG və CSS istifadə edərək həyat üçün məlumat gətirir.

Tez-tez başqa bir layihədə bir qrafiki yenidən istifadə etməli və ya digərləri ilə paylaşmalıyıq. Bunun üçün Mayk Bostok (D3 yaradıcısı) təkrar istifadə edilə bilən diaqramlar adlanan bir model təklif etdi. Onun yanaşmasını Pablo Navarro Castillo tərəfindən Mastering D3.js kitabında təqdim olunanlar kimi bəzi kiçik dəyişikliklərlə istifadə edəcəyik.

Burada D3 4.6.0 versiyasını istifadə edirik.

E Yenidən istifadə olunan qrafiklər

Yenidən istifadə edilə bilən qrafik nümunəsinə əməl edən qrafiklər iki xüsusiyyətə malikdir:

  • Konfiqurasiya. Kodun özünü dəyişdirmədən diaqramın görünüşünü və davranışını dəyişdirmək istəyirik.
  • Müstəqil şəkildə qurulma bacarığı. İstəyirik ki, hər bir chart elementi müstəqil olaraq məlumat dəstimizdəki bir məlumat nöqtəsinə təyin edilsin. Bu, D3 məlumat nümunələrini DOM elementləri ilə necə bağladığı ilə əlaqədardır. Bu bir dəqiqədən sonra aydınlaşacaqdır.
"Nəticə: Diaqramları getter-setter üsulları ilə bağlama şəklində tətbiq edin." - Mayk Bostok

Bubble chart

Əvvəlcə diaqramın hansı elementlərinin tənzimlənə biləcəyini təyin etməlisiniz:

  • Diaqramın ölçüsü
  • Giriş məlumat bazası

Diaqramın ölçüsünü təyin edin

Diaqramın bütün dəyişənlərini əhatə edən və standart dəyərləri təyin edən bir funksiya yaratmağa başlayaq. Bu quruluşa nəticə deyilir.

// bubble_graph.js
var bubbleChart = funksiya () {var en = 600, boy = 400; Fəaliyyət planı (seçim) {// bura gələcəksiniz} qayıtma masası; }

Kod dəyişdirmədən müxtəlif ölçülü diaqramlar yaratmaq istəyirsən. Bunu etmək üçün aşağıdakı kimi diaqramlar yaradın:

// qabarcaq_qraf.html
var diaqram = bubbleChart (). Genişlik (300). Boy (200);

Bunu etmək üçün indi dəyişənlərin eni və hündürlüyü üçün istifadəçiləri təyin edirsiniz.

// bubble_graph.js
var bubbleChart = funksiya () {var en = 600 hündürlük = 400;
Fəaliyyət planı (seçim) {// Bura gəlirik} chart.width = funksiya (dəyər) {əgər (! Argument.length) {qayıtmaq eni; } eni = dəyəri; Qayıt masası; }
chart.height = funksiya (dəyər) {əgər (! arqumentlər.length) {qayıtmaq hündürlüyü; } Boy = dəyər; Qayıt masası; } Qayıt masası; }

BubbleChart () (eni və ya hündürlük atributları olmayan) adlandırdıqda, qrafik bağlanışda müəyyənləşdirdiyiniz genişlik və hündürlük üçün standart dəyərlərlə yaradılır. Metod arqumentlər olmadan çağırılırsa, dəyişən dəyəri qaytarır.

// qabarcaq_qraf.html
var chart = bubbleChart (); qabarcıq qrafiki (). eni (); // 600 qaytarır

Metodların chart funksiyasını niyə geri qaytardığına dair sualınız ola bilər. Bu kodu sadələşdirmək üçün istifadə olunan JavaScript nümunəsidir. Metod zənciri adlanır. Bu nümunə ilə yeni obyektlər yarada bilərsiniz:

// qabarcaq_qraf.html
var diaqram = bubbleChart (). Genişlik (600). Boy (400);

yerinə:

// qabarcaq_qraf.html
var chart = bubbleChart (); chart.setWidth (600); chart.setHight (400);

Verilənləri diaqramımıza qoşun

İndi məlumatları chart elementlərinə necə bağlayacağımızı öyrənək. Diaqram necə qurulmuşdur: Diaqram ilə div SVG elementinə malikdir və hər bir məlumat nöqtəsi diaqramdakı bir dairəyə uyğundur.

// bubble_graph.html bubbleChart () funksiyasını çağırdıqdan sonra
// məlumatlardan bir hekayə // məlumatdan başqa bir hekayə ...

🗄 d3.data ()

D3.selection.data ([data [, key]]) funksiyası, məlumatla uğurla bağlı olan bir elementi təmsil edən yeni bir seçimi qaytarır. Bunu etmək üçün əvvəlcə məlumatları CSV sənədindən yükləməlisiniz. Siz d3.csv (url [[, row], callback]) funksiyasından istifadə edəcəksiniz.

// qabarcaq_qraf.html
d3.csv ('file.csv', funksiya (səhv, bizim_data) {var data = our_data; // burada məlumatla istədiyinizi edə bilərsiniz}
// orta_january.csv | başlıq | Kateqoriya | Ürəklər | | -------------------------------------- | ---------- ---- | -------- | | Heç kim proqram inkişafından istifadə etmək istəmir 2700 | | Yolları ilə itkisiz veb naviqasiya Dizayn | 688 | | Məlumat Mühəndisi Məlumat Elminin yüksəlişi | 862 |

🖍 d3 seçimi

Məlumatlarımızı diaqrama ötürmək üçün d3-select () və data () funksiyalarından istifadə edəcəksiniz.

Seçim, Document Object Model (DOM) tərəfindən güclü, məlumat yönlü bir çevrilməyə imkan verir: atributlar, üslublar, xüsusiyyətlər, HTML və ya mətn məzmunu və daha çox. - D3 sənədləri
// qabarcaq_qraf.html
d3.csv ('orta_january.csv', funksiya (səhv, bizim_data) {if (səhv) {console.error ('Verilənləri əldə etmək və ya təhlil etməkdə səhv.'); atma xətası;}
var diaqram = bubbleChart (). Genişlik (600). Boy (400); d3.select ('# chart'). data (our_data) .call (chart);
});

Başqa bir vacib selektor d3.selectAll () -dir. Tutaq ki, aşağıdakı quruluş var:


    
    
    

d3.select ("bədən"). SelectAll ("div") bütün bu divləri bizim üçün seçir.

d3.enter ()

İndi əhəmiyyətli bir D3 funksiyası ilə tanış olursunuz: d3.enter (). Boş bir bədən etiketiniz və bir sıra məlumatınız var deyin. Serialın hər bir elementindən keçmək və hər element üçün yeni bir div yaratmaq istəyirsən. Bunu aşağıdakı kodla edə bilərsiniz:

 // boş 
---- // js yazısı
var bizim_data = [1, 2, 3] var div = d3.select ("bədən") .selectAll ("div") .data (bizim_data) .enter (). əlavə et ("div"); ---


    
    
    

Divlər hələ mövcud deyilsə niyə SelectAll ("div") lazımdır? Çünki D3-də bir şeyi necə edəcəyimizi söyləmək əvəzinə istədiyimizi söyləyirik.

Bu vəziyyətdə serialın bir elementini hər divə təyin etmək istəyirsiniz. Bunu SelectAll ("div") ilə deyirsiniz.

var div = d3.select ("bədən") .selectAll ("div") // burada 'hey d3, sonrakı gələn serialın hər məlumat elementi bir div' ilə əlaqələndirilir '.data (our_data) .enter (). əlavə et ("div");

Enter düyməsini () seçimi serialın elementinə bağlanan məlumatlarla qaytarır. Sonra bu seçimi .append ("div") istifadə edərək DOM-a əlavə edin.

d3.forceSimulyasiya ()

Dairələrin fizikasını simulyasiya etmək üçün bir şeyə ehtiyacınız var. Bunun üçün d3.forceSimulation ([node]) istifadə edirsiniz. Ayrıca hansı gücün düyünlərin vəziyyətini və ya sürətini dəyişdirdiyini də göstərməlisiniz.

Bizim vəziyyətimizdə d3.forceManyBody () istifadə edirik.

// bubble_chart.js
var simulyasiya = d3.forceSimulyasiya (məlumat). qüvvə ("şarj", d3.forceManyBody (). gücü ([- 50])). güc ("x", d3.forceX ()) .force ("y", d3.forceY ()) .on ("işarə", işarələnmişdir);

Müsbət bir güc dəyəri düyünlərin bir-birlərini cəlb etməsinə səbəb olur, mənfi bir güc dəyəri isə onların bir-birini təkzib etməsinə səbəb olur.

Güc () təsiri

Bununla birlikdə, qovşaqların bütün SVG boşluğunu əhatə etməsini istəmirik, buna görə d3.forceX (0) və d3.forceY (0) istifadə edirik. Bu dairələri 0 vəziyyətinə "sürükləyir". Nə baş verdiyini görmək üçün bunu koddan çıxartmağa çalışın.

Səhifəni yenilədikdə, dairələrin nəhayət sabitləşənə qədər tənzimləndiyini görə bilərsiniz. İşarələnmiş () funksiyası dairələrin mövqelərini yeniləyir. D3.forceManyBody () hər nodun x və y mövqeyini daim yeniləyir və işarələnmiş () funksiyası DOM-u bu dəyərlərlə (cx və cy atributları) yeniləyir.

// bubble_graph.js
Yoxlanılan funksiya (e) {node.attr ("cx", funksiya (d) {qayıt dx;}) .attr ("cy", funksiya (d) {qayıtmaq dy;}); // 'node' qabarcaq sxemindəki hər hansı bir dairədir
}

Budur hər şeyin kodu:

var simulyasiya = d3.forceSimulyasiya (məlumat). qüvvə ("şarj", d3.forceManyBody (). gücü ([- 50])). güc ("x", d3.forceX ()) .force ("y", d3.forceY ()) .on ("işarə", işarələnmişdir);
Yoxlanılan funksiya (e) {node.attr ("cx", funksiya (d) {qayıt dx;}) .attr ("cy", funksiya (d) {qayıtmaq dy;}); }

Xülasə olaraq demək olar ki, bu simulyasiya hər bir dairəyə x və y mövqeyi verir.

d3. tərəzi

Budur ən maraqlı hissə gəlir: dairələri əlavə etmək. Enter () funksiyasını xatırlayırsınız? İndi istifadə edəcəksən. Cədvəlimizdə, hər dairənin radiusu hər hekayə üçün tövsiyələrin sayına mütənasibdir. Bunu etmək üçün xətti bir miqyas istifadə edin: d3.scaleLinear ()

Tərəzi istifadə etmək üçün iki şeyi müəyyənləşdirməlisiniz:

  • Domain: giriş məlumatlarının minimum və maksimum dəyərləri (vəziyyətimizdə tövsiyələrin minimum və maksimum sayı). Minimum və maksimum dəyərləri əldə etmək üçün d3.min () və d3.max () funksiyalarından istifadə edin.
  • Aralığı: Miqyasın minimum və maksimum çıxış dəyəri. Bizim vəziyyətimizdə ən kiçik radius 5 və ən böyük radius 18 istəyirik.
// bubble_graph.js
var miqyaslıRadius = d3.scaleLinear () .domain ([d3.min (data, function (d) {return + d.views;})), d3.max (data, function (d) {return + d.views); })]) .range ([5,18]);

Və sonra nəhayət dairələri yaradın:

// bubble_graph.js
var node = svg.selectAll ("Kreis") .data (məlumat daxil edin) (). əlavə et ("dairə") .attr ('r', funksiya (d) {miqyaslıRadius (d.views) qayıtmaq})}) ;

Dairələri rəngləndirmək üçün, kateqoriyalı bir miqyas istifadə edin: d3.scaleOrdinal (). Bu miqyas diskret dəyərləri qaytarır.

Məlumat dəstimiz 3 kateqoriyaya malikdir: dizayn, inkişaf və məlumat elmi. Bu kateqoriyaların hər birini bir rəngə təyin edirsiniz. d3.schemeCategory10 bizə 10 rəngdən ibarət bir siyahı təqdim edir, bu da bizim üçün kifayətdir.

// bubble_graph.js
var colorCircles = d3.scaleOrdinal (d3.schemeCategory10); var node = svg.selectAll ("Kreis") .data (məlumat daxil edin) (). əlavə et ("dairə") .attr ('r', funksiya (d) {qayıtmaq miqyasıRadius (d.views)}) .style ("doldur", funksiya (d) {geri qayıt colorCircles (d.category)});

Dairələrin SVG faylının ortasında çəkilməsini istəyirsinizsə, hər dairəni mərkəzə (eni yarısı və hündürlüyün yarısı) keçirin. Nə baş verdiyini görmək üçün koddan çıxarın.

// bubble_graph.js
var node = svg.selectAll ("Kreis") .data (məlumat daxil edin) (). əlavə et ("dairə") .attr ('r', funksiya (d) {qayıtmaq miqyasıRadius (d.views)}) .style ("doldur", qayıtmaq funksiyası (d) {colorCircles (d.category)}) .attr ('çevir', 'tərcümə (' + [en / 2, boy / 2] + ')');

İndi diaqrama alət göstərişlərini əlavə edin. Siçanı dairələr üzərində hərəkət etdirdiyimiz zaman göstərilməlidir.

var tooltip = seçim. əlavə et ("div") .stil ("mövqe", "mütləq") .stil ("görünürlük", "gizli") .stil ("rəng", "ağ") .stil ("padding" , "8px") .stil ("background color", "# 626D71") .style ("frame radius", "6px") .style ("text align", "center") .style ("font family", "monospace" ) .stil ("en", "400px") .Mətn ("");
var node = svg.selectAll ("Kreis") .data (məlumat daxil edin) (). əlavə et ("dairə") .attr ('r', funksiya (d) {qayıtmaq miqyasıRadius (d.views)}) .style ("doldur", qayıtmaq funksiyası (d) {colorCircles (d.category)}) .attr ('çevirmək', 'tərcümə etmək (' + [en / 2, boy / 2] + ')') .on ("mouseoverover ", Funksiya (d) {tooltip.html (d.category +" "+ d.title +" "+ d.views); return tooltip.style (" görünürlük "," görünən ");}) .on (" mousemove ", funksiya () {return tooltip.style (" top ", (d3.event.pageY- 10) + "px"). Stil ("sol", (d3.event.pageX + 10) + "px");}) .on ("mouseout", function () {return tooltip.style ("görünürlük" , "gizli");});

Siçan göstərici siçan hərəkət edərkən kursoru izləyir. d3.event.pageX və d3.event.pageY siçan koordinatlarını qaytarır.

Və budur! Son kodu burada görə bilərsiniz.

Burada baloncuk masası ilə oynaya bilərsiniz.

Bu məqaləni faydalı hesab etdinizmi? Çalışıram ki, hər ay dərin bir dalış məqaləsi yazım. Yenisini göndərdiyim zaman bir e-poçt ala bilərsiniz.

Suallar və ya təkliflər? Onları şərhlərdə buraxın. Oxuduğunuz üçün təşəkkür edirik!

John Carmichael və Alexandre Cisneiros'a xüsusi təşəkkürlər.