Как создать график на SVG

Как создать график на SVG

От автора: в своей первой статье о создании графиков я использовал методы на чистом 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:

<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:

<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:

.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. Таким образом, мы выровняем все столбцы по нижнему краю. Ниже краткий код примера:

<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 — точки вершин:

<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. Он задокументировал пару интересных свойств, которые помогут нам создать надписи и стилизовать оси графиков. Мы воссоздадим упрощенную версию его примера:

<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. Сначала, разметка:

<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>

Теперь зададим данные о населении:

var continents = {
  asia: 60,
  northAmerica : 5,
  southAmerica: 9,
  oceania: 1,
  africa: 15,
  europe: 12
};

Необходимо заполнить пустые блоки .buttons кнопками, по клику на которые будет меняться свойство stroke-dasharray для SVG элемента circle. Кнопки можно создать так:

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 процентов, а не от окружности. Создадим функцию для этого:

var total = 158; 

var numberFixer = function(num){
  var result = ((num * total) / 100);
  return result;
}

Теперь добавим обработчик события к каждой кнопке, создадим функцию setPieChart(). Данная функцию меняет значение stroke-dasharray, проверяет атрибут data-name каждой кнопки и находит соответствующую информацию:

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:

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

Источник: https://css-tricks.com/

Редакция: Команда webformyself.

Курс по HTML5: основы

Изучите HTML5 с нуля!

Смотреть курс

Метки:

Комментарии Вконтакте:

Комментарии Facebook:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Я не робот.

Spam Protection by WP-SpamFree