По-рано направихме първия си пример за d3 работещ. Не беше много сложно (надявам се). Използвахме select, selectAll, data, enter и т.н.... Говорих малко за аналогията с множествата, но не в много подробности. Днес бих искал да направя крачка назад и да говоря малко повече за селекциите(данните ще дойдат утре).

Изберете

Нека започнем с нещо просто. Как да изберем първия елемент в примера по-долу?

За да изберем първия елемент, който можем да използваме:

d3.select('#foo');

Това ще ни върне масив с един елемент в него. Елементът ще бъде препратка към нашия елемент ‹div id=”#foo”›.

Ако погледнете препратката, която се връща в масива, ще видите свойство, наречено „parrentNode“ (както на изображението по-долу):

Ще намерите това свойство за полезно на по-късен етап. Засега просто помнете, че съществува.

Друг начин за избор на същия елемент би бил:

d3.select('div');

Това ще ни даде масив с един елемент в него. Този път ще ни върне само първия елемент, който отговаря на нашия селектор. В този случай първият елемент е нашият ‹div id=”#foo”› елемент.

Избери всички

SelectAll се използва за избиране на няколко елемента едновременно.

Например:

d3.selectAll('div')

Това ще избере всички елементи „div“.

Забележете, че тази селекция също има „parentNode“.

Как да изберем всички „svg“ елементи? Е, можем да направим това:

d3.selectAll('svg')

Това ще ни даде масив с три елемента, които случайно са нашите svg елементи.

Обърнете внимание на „parrentNode“ в селекцията.

Сега нека се опитаме да изберем всички ‘svg’ елементи, които са дъщерни на ‘div’ елемент:

d3.selectAll('div svg');

Резултатът, който получавате, трябва да е същият като преди:

За да изберем всички ‘svg’ елементи, които са дъщерни на някакъв div елемент, можем първо да получим селекция от ‘div’ елементи и след това оттам да изберем нашите ‘svg’ елементи: Както в:

d3.selectAll('div').select('svg');

Резултатът в този пример е еквивалентен на примера с един селектор („div svg“).

Сега нека опитаме да изберем всички елементи „div“ и след това всички елементи „svg“ в рамките на тези „div“.

d3.selectAll('div').selectAll('svg')

Сега получаваме малко по-различен резултат:

Резултатът е масив от масиви... Това е страхотно. d3 запазена йерархична структура на елементи в DOM. Това е много полезно свойство на d3, което ще ви помогне с вашите визуализации.

Препоръчвам ви да си поиграете с d3 селекциите и да разберете как работят. Това е много важно.

Работа с елементи

След като вече знаем как да избираме елементи, нека видим как можем да работим с тях.

Нека започнем с модифицирането само на първия елемент „div“ („#foo“). За да го различим от другите елементи, ще го направим червен. За да направим това, трябва да зададем свойството ‘background-color’ на ‘red’.

За да работи с атрибути, селекцията d3 има метод „attr“ (https://github.com/d3/d3/wiki/Selections#attr).

Правила 1: Операторите на съдържанието прилагат промяна към всички елементи в селекцията.

Правило 2: Операторите за съдържание връщат текущата селекция, така че можете да свържете няколко оператора заедно в сбито изявление.

Така че, за да направим нашия елемент „#foo“ червен, ние правим:

d3.select('#foo').attr('style', 'background-color: red');

Какво ще кажете, ако искаме да направим всички наши div елементи червени. Е, можем да използваме selectAll вместо select. Също така трябва да избираме по име на етикет („div“), а не по id („#foo“).

d3.selectAll('div').attr('style', 'background-color: red');

Е, сега, когато всички наши div елементи са червени, вече не можем да различим.

Ако погледнете d3 документацията за метода attr, ще видите, че не е нужно да присвояваме статична стойност. Нашата стойност всъщност може да бъде функция. Ако предоставим функция вместо статична стойност, за всеки елемент, за който d3 задава атрибут, първо ще оцени функцията, за да види каква трябва да бъде тази стойност. Функцията ще бъде извикана с два аргумента — datum и index (обикновено съкратено като „d“ и „i“съответно).

Така че нека зададем различни цветове на нашите елементи. Ще съхраняваме цветовете, които искаме да използваме, в масив (удобно), наречен цветове:

var colors = ['red', 'green', 'blue'];

И сега можем да изберем нашите елементи и да приложим цвят на фона въз основа на индекса в селекцията:

d3.selectAll('div')
  .attr('style', function(d, i) { 
    return 'background-color: ' + colors[i];
  });

Сега нека направим нещо малко по-сложно. Нека добавим параграф към всеки div и съдържанието на параграфа трябва да бъде индексът на елемента „div“.

Нека започнем с вмъкването на p елементи в нашите div елементи:

var inserted = d3.selectAll('div').append('p')

append ще ни върне нова селекция (както се вижда на снимката по-долу):

Сега можем да използваме метода html върху селекцията, за да зададем съдържание.

inserted.html(function(d, i) { return i; } );

Ако погледнете какво върна методът html, ще забележите, че той също върна същата селекция.

Тази функция на d3 (връщане на селекции) ви позволява лесно да свързвате методи/операции. Двата примера по-горе могат да бъдат написани като:

d3.selectAll('div')
  .append('p')
  .html(function(d, i) { return i; } );

Ще видите този модел използван много често в d3.

Резюме

Видяхме как d3 третира селекциите. Използвахме функциите select, selectAll, attr и html, дефинирани при избора. Ще ги използвате много често и се надявам да ги разберете много добре. Ако не, силно препоръчвам да ги разберете, преди да преместите такъв. d3 има наистина добра документация, така че я препращайте често.