Візуалізація даних на JS
D3 (Data-Driven Documents — Керування даними в документах [досл.]). Вона дозволяє «оживити» ваш проект, використовуючи довільні дані, поєднати їх із HTML, CSS і SVG (Scalable Vector Graphic — Векторна графіка), динамічно маніпулюючи елементами DOM (Document Object Model — Об'єктна модель документа) і на виході отримати, наприклад, лінійну діаграму або будь-який інший об'єкт/картинку. З реального використання D3 можна назвати такі важливі застосування, як побудова графіків, створення карти, з використанням координат та інше.
Що ж мається на увазі під даними? Дані — це будь-яка інформація, що потенційно містить певний зміст, причому як явного, так і неявного характеру і застосовуючи візуалізацію до даних у такій постановці питання, можна цей сенс уявити у досить наочному вигляді. У найпростішому вигляді ми можемо уявити дані, як масив чисел, що описують якийсь сенс, наприклад те саме голосування у вигляді лінійного графіка, скільки проголосувало за «добре», а скільки за «погано». На вході надходять дані (користувач вибрав варіант, цей варіант обробився), а на виході ми бачимо відображення для виконаних дій, голос зарахований, підсумовувався з попередніми голосами і загальна картинка представилася у вигляді графіка.
Що нам надає D3? Бібліотека дає нам всі необхідні інструменти для обробки даних та маніпулювання DOM (на зразок jQuery, зокрема побудова ланцюжків методів). Дані бібліотеки мають дуже велику схожість один з одним, оскільки мають вбудовані процедури маніпулювання DOM, розпізнають CSS-селектори (вибірку елементів) і ґрунтуються на веб-стандартах, але все ж таки відрізняються один від одного за призначенням. jQuery - обгортка над стандартним JS, що є в будь-якому браузері, бібліотека загальногопризначення, призначена для полегшення безлічі операцій, що проробляються на звичайному JS, в той час як D3 призначається для маніпуляції даними (їх візуалізації, фільтрації, трансформацією, генеруванням і т.д.), підтримує роботу з векторною графікою та містить різні механізми прив'язування даних до html-документу.
Давайте трохи потренуємося в малюванні примітивів векторної графіки, заодно згадаємо (або дізнаємося, для кого як) як взагалі описати засобами html розмітки такі геометричні фігури, як лінії та кола. Намалюємо, наприклад ось такий вигаданий графік, з осями координат і лінією під 45 градусів, накладемо на цей графік коло так щоб лінія проходила через неї і перетинала навпіл:
Ми намалювали дані фігури і позначили їх параметри статично, але вся краса в тому, що D3 дозволяє нам залежно від даних робити це все в динаміці, - ще раз повторюся, чи то малювання простих графіків, чи просто захоплюючих дух, приклади візуалізації.
Тепер спробуємо зробити той же «химерний» графік, але вже в динаміці, методами D3. Спочатку підключимо D3, наприклад так:
Потім створіть елемент:
І пропишіть наступний код:
Проаналізувавши цей лістинг, можна переконатися, що D3 працює майже як і jQuery. Спочатку йде вибірка елементів, ми вибираємо ту область куди додаватимемо наші нові елементи, вставляємо їх і присвоюємо їм атрибути, навіть однойменні методи, що дуже тішить. А надаючи дані в процесі додавання елементів, ми привносимо динаміку! Ось такий найпростіший приклад вже повинен показати вам як усе.
Код вище можна, і потрібно, звичайно, оптимізувати, задавши масив координат і прогнати все в циклі, таким чином прибратишматки коду, що повторюються, але ми тут не про оптимізацію коду, а про основи і можливості бібліотеки. Йдемо далі.
Але навіть використання циклів у програмному коді при використанні бібліотеки D3 не зовсім коректно, так як у неї є власна концепція роботи з масивами даних і полягає вона в тому, що при роботі з великим масивом довільних даних програміст працює також, якби працював з одним елементом.
Концепція D3
Тепер створимо новий HTML5 документ і позначимо там деякі важливі теги, в яких надалі писатимемо скрипти:
Цей порожній документ - заготівля для того, щоб побудувати динамічну діаграму випадкових чисел, але в той же час на цьому простому прикладі ми досліджуємо одну з трьох можливих важливих ситуації при роботі з D3: реалізація вхідного потоку Enter на сторінці.
Ситуація вхідного потоку Enter виникає тоді, коли елементів DOM менше, ніж кількість даних, або елементів DOM немає зовсім, а дані є. У такому випадку з безлічі елементів виділяється підмножина елементів, які необхідно додати на сторінку спеціальним для цього методом .append( )
Вставимо скрипт генерації масиву наш документ замість // . функція генерації масиву. вище закриває тега head і відразу після функції сформуємо дані: var randData = numRand(50); випадкові числа в діапазоні 0..50. В даний момент у нас є порожній div, тобто в ньому ще немає абсолютно ніяких елементів DOM, але вже є дані, змінна randData містить масив випадкових чисел!
Додамо статичні стилі для нашої діаграми, для цього замість /інлайн стилі/, створимо правило, яке описуватиме стовпці нашої діаграми:
Клас .bar задасть однакову ширину для стовпців,відступи та колір шрифту всередині. Тепер де фраза // . скрипт D3. вставимо скрипт, який здійснює прив'язку даних масиву та створює елементи DOM усередині div методом .append( ):
Метод .data() пов'язує дані масиву з вибіркою, яку повернув метод .selectAll(). Тут ми встановлюємо що новоствореними елементами будуть span, але оскільки даних елементів в даний час немає, то ми резервуємо місце виходячи з того, що кожному елементу з масиву даних відповідає елемент DOM span. Метод .enter( ) тим часом виділяє підмножина доданих елементів (виходить стільки ж елементів span, скільки елементів у масиві randData). Метод .append( ) безпосередньо додає елементи до DOM.
Для того щоб висота стовпців відповідала числовим значенням масиву, для кожного знову доданого елемента динамічно формується висота і колір за допомогою callback-функції function(d, i), куди передається значення d і i, це поточне значення елемента масиву і його порядковий номер, а в тілі функції ми повертаємо результат, наприклад, для висоти: < return 3*d+"px" >, я повертаю потрійне значення поточного елемента масиву, через що можна стверджувати що максимальна висота стовпця може бути 150px і мінімальна 0. Аналогічно можна обробляти колір стовпців!
Безліч Exit та Update
Вище ми розглянули ситуацію, коли формується безліч вхідного потоку Enter і реалізували найпростішу вертикальну діаграму, засновану на додаванні елементів DOM, для яких є дані в масиві. Але є й протилежна ситуація: коли даних менше, ніж елементів на сторінці, яким будуть відповідати ці дані, в такому разі такі елементи автоматично потрапляють у підмножину Exit і згодом видаляються методом .remove( ).
Ситуація вихідного потоку Exit виникає тоді, коли елементів DOM більше, ніж кількість даних. У такому випадку з безлічі елементів виділяється підмножина елементів, яким немає відповідності даним і які необхідно видалити зі сторінки спеціальним для цього методом .remove( )
Багато Update відповідають елементам, для яких є відповідні елементи масиву і є елементи DOM, але значення яких змінилися. Ця ситуація знаходиться між Enter та Exit.