От автора: в своей первой статье о создании графиков я использовал методы на чистом CSS. Я говорил, что это далеко не лучшие решения в большинстве случаев; слишком много костылей в дизайне придется сделать. А вообще, самым лучшим решением будет комбинация из SVG, JS и CSS для создания графиков.
Почему на canvas?
Существует множество способов создания графиков в сети, а особенно на canvas. Тем не менее, Sara Soueidan советует избегать этого метода:
«HTML5 Canvas тоже можно использовать для создания визуализации, однако генерируемый контент не является частью DOM и к нему нельзя получить доступ. Для решения данной проблемы, вам бы пришлось дублировать контент между открывающим и закрывающим тегом canvas. Такое решение также обеспечивает фоллбэк для старых браузеров. Также придется связать фоллбэк контент с холстом, чтобы при взаимодействии элементы реагировали правильно. Так что в HTML5 Canvas нам потребуется продублировать весь контент […] А в SVG вы сразу получаете семантичность и доступность вместе с интерактивностью на JS прямо из коробки.»
Но кроме холста есть и другие способы. К примеру, Filament Group написали JQuery плагин под названием Visualize, который собирают всю информацию из таблицы table и на основе полученных данных создает график. Данный метод имеет место, даже если в таблице всего один элемент.
Почему SVG?
Формат SVG предназначен не только для иконок или простых изображений. У него есть свои преимущества для создания графиков. В нашем гайде по SVG мы описали основные преимущества данного формата так:
Маленький размер файлов с хорошим сжатием
Полная масштабируемость (кроме совсем крошечных размеров)
Отлично подходит для ретина дисплеев
Взаимодействие и фильтры
А также можно добавить два ключевых преимущества, которые будут полезны для графиков:
SVG доступен в браузерах (придется совсем немного поработать)
Для помощи можно посмотреть множество SVG фреймворков предназначенных для создания графиков
Начнем. Как же проще всего создать график на SVG?
Графики с помощью img
Создавать графики в SVG так же легко, как и в Illustrator или в другом векторно-ориентированном приложении, затем экспортировать это в SVG и вставить в разметку через тег img:
1 |
<img src="chart.svg" alt="Hopefully you can impart equally useful alternate content here."> |
Это довольно-таки хороший способ, плюс изображение хорошо масштабируется. Но все же мы теряем большинство преимуществ встроенного SVG, в том числе доступ через DOM и взаимодействие. Браузеры никак не считывают такие графики, считывается только атрибут alt, а также теряется взаимодействие с мышкой, тачскрином или клавиатурой.
Все эти проблемы наталкивают на поиск другого способа вставки SVG в разметку страницы. К примеру, что, если поступить так же, как в проекте Death from Above? Используемый там способ взаимодействия с графиками поможет нам все понять.
Чтобы добиться максимума от SVG, необходимо взять весь код из этого примера и вставить его к себе на страницу. Графы (вершины графиков) можно стилизовать с помощью CSS, изменить интерактивность с помощью JS – так мы выжмем все преимущества от встроенного SVG.
(Добиться таких же результатов можно с помощью object или iframe, концепции очень похожи. Но рассмотрим подробнее инлайновый SVG.)
Столбчатые диаграммы
Каждая колонка графика это тег <g> (на языке SVG группа элементов). Внутри каждой группы мы разместим прямоугольники rect, они зададут форму графикам. Рядом с прямоугольником добавим текст text, где будем отображать числа. Ниже готовый пример:
Спозиционировать элементы rect и text можно с помощью координат x/y:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<svg class="chart" width="420" height="150" aria-labelledby="title desc" role="img"> <title id="title">A bar chart showing information</title> <desc id="desc">4 apples; 8 bananas; 15 kiwis; 16 oranges; 23 lemons</desc> <g class="bar"> <rect width="40" height="19"></rect> <text x="45" y="9.5" dy=".35em">4 apples</text> </g> <g class="bar"> <rect width="80" height="19" y="20"></rect> <text x="85" y="28" dy=".35em">8 bananas</text> </g> <g class="bar"> <rect width="150" height="19" y="40"></rect> <text x="150" y="48" dy=".35em">15 kiwis</text> </g> <g class="bar"> <rect width="160" height="19" y="60"></rect> <text x="161" y="68" dy=".35em">16 oranges</text> </g> <g class="bar"> <rect width="230" height="19" y="80"></rect> <text x="235" y="88" dy=".35em">23 lemons</text> </g> </svg> |
Обратите внимание, при наведении на график изменяется цвет столбца и текста. Управлять этим можно с помощью CSS свойства fill:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
.bar { fill: red; /* changes the background */ height: 21px; transition: fill .3s ease; cursor: pointer; font-family: Helvetica, sans-serif; } .bar text { color: black; } .bar:hover, .bar:focus { fill: black; } .bar:hover text, .bar:focus text { fill: red; } |
Вот так просто, SVG с возможностью взаимодействия! Но и в этом способе не без проблем: переключение между графами не работает (т.к. в браузере еще не поддерживается аттрибут focusable). У Léonie Watson есть пара советов по SVG. Для фокусировки можно использовать <a xlink:href=»#»> — а что если область фокусировки это не ссылка? Данную проблему мы рассмотрим в следующих статьях.
Инфокривые
Так как инфокривые во многом это крошечные гистограммы, то мы позаимствуем большинство кода из предыдущего примера:
В этот раз чтобы выровнять группы <g> можно использовать свойство transform (конечно, лучше использовать x и y координаты, но способ такой есть). Чтобы информация корректно отображалась, изменим атрибут height в элементе rect, и сдвинем каждый столбец графика вниз по оси y. Таким образом, мы выровняем все столбцы по нижнему краю. Ниже краткий код примера:
1 2 3 4 5 6 |
<g class="bar" transform="translate(0,0)"> <rect height="10" y="10" width="3"></rect> </g> <g class="bar" transform="translate(3,0)"> <rect height="6" y="14" width="3"></rect> </g> |
Линейные графики
Тег polyline поможет нам задать линии, а атрибут points — точки вершин:
1 2 3 4 5 6 7 8 9 10 11 |
<svg viewBox="0 0 500 100" class="chart"> <polyline fill="none" stroke="#0074d9" stroke-width="3" points=" 0,120 20,60 40,80 60,20"/> </svg> |
0,120 значит 0 слева и 120 сверху на холсте SVG. Когда мы определились с вершинами графика, можно задать ширину линии с помощью stroke-width, цвет линии с помощью stroke:
Но это только стили графика – а что насчет основных линий, помогающим понять, что к чему? Что по поводу осей?
Создание осей и надписей
Roemer Vlasveld написал отличную статью о создании графиков на SVG. Он задокументировал пару интересных свойств, которые помогут нам создать надписи и стилизовать оси графиков. Мы воссоздадим упрощенную версию его примера:
1 2 3 4 5 6 7 8 |
<svg class="graph"> <g class="grid x-grid"> <line x1="90" x2="90" y1="5" y2="371"></line> </g> <g class="grid y-grid"> <line x1="90" x2="705" y1="370" y2="370"></line> </g> </svg> |
Каждая группа <g> используется для создания горизонтальных и вертикальных линий, и в сочетании с правильно расположенными надписями мы уже получаем половину графика, только без самой линии:
Добавив в другую группу все точки с помощью элемента circle, можно посмотреть, что получится:
Круговые диаграммы
Мы уже пару раз упомянули статью Lea Verou о круговых диаграммах, так как это отличный пример. С него мы и начнем. Не буду заново объяснять ее технику здесь, хотя было бы интересно посмотреть, как можно взаимодействовать с круговыми диаграммами в SVG. Ниже готовый пример, чтобы вы поняли, к чему мы стремимся:
При нажатии на кнопки над самим графиком, он обновляется. Значения берутся из JS объекта. В этом методе также есть свои проблемы с доступностью, но я заострю внимание на взаимодействии с помощью JS и SVG. Сначала, разметка:
1 2 3 4 5 6 7 8 9 10 11 |
<figure> <figcaption> Percentage of world population by continent </figcaption> <div class="buttons"></div> <svg width="100" height="100" class="chart"> <circle r="25" cx="50" cy="50" class="pie"/> </svg> </figure> |
Теперь зададим данные о населении:
1 2 3 4 5 6 7 8 |
var continents = { asia: 60, northAmerica : 5, southAmerica: 9, oceania: 1, africa: 15, europe: 12 }; |
Необходимо заполнить пустые блоки .buttons кнопками, по клику на которые будет меняться свойство stroke-dasharray для SVG элемента circle. Кнопки можно создать так:
1 2 3 4 5 6 7 8 |
var buttons = document.querySelector('.buttons'); for(property in continents) { var newEl = document.createElement('button'); newEl.innerText = property; newEl.setAttribute('data-name', property); buttons.appendChild(newEl); } |
Теперь исправим проценты: asia: 60 в объекте continents значит 60 от 100 процентов, а не от окружности. Создадим функцию для этого:
1 2 3 4 5 6 |
var total = 158; var numberFixer = function(num){ var result = ((num * total) / 100); return result; } |
Теперь добавим обработчик события к каждой кнопке, создадим функцию setPieChart(). Данная функцию меняет значение stroke-dasharray, проверяет атрибут data-name каждой кнопки и находит соответствующую информацию:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
buttons.addEventListener('click', function(e){ if(e.target != e.currentTarget) { var el = e.target, name = el.getAttribute('data-name'); setPieChart(name); setActiveClass(el); } e.stopPropagation(); }); var setPieChart = function(name) { var number = continents[name], fixedNumber = numberFixer(number), result = fixedNumber + ' ' + total; pie.style.strokeDasharray = result; } |
Добавив эти вспомогательные функции, получаем готовую круговую диаграмму:
Манипуляция SVG с помощью CSS и JavaScript
Анимация в предыдущих примерах была довольна проста, все, что мы делали, это использовали свойство transition:
1 2 3 |
circle { transition: stroke-dasharray .3s ease; } |
После того, как мы изменили значение свойства с помощью скрипта, остальную работу за нас делает CSS. А какими еще SVG свойствами и атрибутами можно манипулировать через CSS?
Особенность стилизации SVG с помощью CSS в том, что мы можем контролировать только некоторые свойства. К примеру, если мы хотим изменить x или y координаты, или группу <g> (не используя свойство transform), придется подключать JS. А еще хуже, если вы вообще не работали с SVG, т.к. свойства CSS применяются только к конкретным элементам.
У W3C есть полезный список, какие свойства влияют на конкретные элементы SVG. Так что дважды проверьте, прежде чем применять свойство CSS к определенному элементу.
Редактирование SVG вручную не самый лучший способ
С такими базовыми формами, как rect, line и polygon можно создать любой тип SVG графиков. Настоящая проблема в другом: а нужно ли нам это? К примеру, линейные графики еще можно создать вручную, но я бы не рекомендовал это делать. Синтаксис слегка сложен, особенно, если необходимо создать кривые линии.
Писать SVG вручную очень медленный и неприятный процесс. Даже при создании простых графиков, потребуется целая вечность, чтобы написать код и проверять позиции каждого элемента графика. Так же, как и при создании графиков на чистом CSS, написание SVG вручную очень болезненный процесс, если вы, конечно, не создаете совсем маленький график. Должен же быть другой, более удобный способ?
Фреймворки в помощь!
В будущих статьях мы обсудим все преимущества (и проблемы) использования фреймворков для создания графиков, а также сравним все популярные фреймворки.
Автор: Robin Rendle
Источник: //css-tricks.com/
Редакция: Команда webformyself.
Комментарии (1)