Статьи

Создайте инфографику с помощью Snap.svg

Snap-SVG логотип

Snap SVG — это новое поколение и естественная эволюция векторной библиотеки Raphael JS Дмитрия Барановского .

Хотя ничто не мешает вам писать сырые SVG, фреймворки, такие как Snap , SVG.JS и Bonsai, могут помочь сгладить некоторые кросс-платформенные и кросс-браузерные проблемы.

Короче говоря, библиотека Snap объединяет все великолепные функциональные возможности технологии SVG, что позволяет нам создавать все виды независимой от разрешения векторной графики — как статической, так и интерактивной — простым и понятным способом.

Он прочно ориентирован на современные браузеры, поэтому, в отличие от Raphael, он поддерживает расширенные функции, такие как маскирование, обрезка, шаблоны, полные градиенты, группы и многое другое.

В этом уроке мы собираемся создать инфографику с нуля, используя большую часть функций, предоставляемых Snap.

Тема, которую я выбрал, касается трех слоев, составляющих каждую веб-страницу (HTML, CSS и JS). Это будет в основном статическая инфографика, но будет также включать анимированный и интерактивный компонент.

Вы можете увидеть окончательный результат на следующем скриншоте:

Пример графика: три слоя каждой веб-страницы

Пример инфографики: три слоя каждой веб-страницы

Начиная

Первое, что нам нужно сделать, это создать новую папку с именем Snap Infographic , в которой будут храниться файлы нашего проекта.

Затем перейдите на домашнюю страницу Snap и загрузите библиотеку. Откройте файл .zip , найдите файл snap.svg.js в папке dist и извлеките его в папку нашего проекта. Затем создайте новый файл с именем infographic.html в той же папке.

Откройте его и добавьте следующий код:

 <!DOCTYPE HTML> <html> <head> <meta charset="utf-8" /> <title>Snap Infographic</title> <script src="snap.svg.js"></script> </head> <body> <script type="text/javascript"> window.onload = function () { var snap = Snap(912,912); }; </script> </body> </html> 

Посмотрим, что у нас здесь.

Сначала внутри тега head мы добавляем ссылку на файл snap.svg.js Далее у нас есть тег script размещенный внутри тега body . Внутри тега script мы создаем переменную snap , которую мы будем использовать как ссылку на библиотеку.

Это создает поверхность рисования SVG с нашими указанными размерами.

Построение инфографики

Для построения инфографики мы будем действовать следующим образом: начнем с добавления первого блока кода после переменной snap , а затем каждый последующий фрагмент будет помещен ниже предыдущего.

Я не буду вдаваться в подробности о каждом методе и его параметрах, потому что это может привести к скуке и ненужным длинным инструкциям. Я объясню только эти части кода, которые являются значительными.

Чтобы найти дополнительную информацию о конкретном методе API, обратитесь к документации Snap .

Фон

Первый компонент, который мы собираемся добавить в нашу инфографику, это фон. Для этого мы создадим узор, состоящий из двух диагональных линий, расположенных за синим прямоугольником.

 var p_line1 = snap.paper.line(0,0, 8,8).attr({stroke: '#00ADEF'}); var p_line2 = snap.paper.line(8,0, 0,8).attr({stroke: '#00ADEF'}); var p_rect = snap.paper.rect(0,0, 8,8).attr({fill: '#3A54A4', opacity: 0.9}); var pattern = snap.paper.g(p_line1, p_line2, p_rect).pattern(0,0, 8,8); var background = snap.paper.rect(0,0, 912,912).attr({fill: pattern}); 

В первых трех строках кода мы создаем элементы, необходимые для шаблона. p_line1 и p_line2 составляют две X-скрещенные линии. p_rect создает слегка прозрачный синий квадрат. Следующий фрагмент кода объединяет элементы шаблона в группе и создает из него фактический шаблон.

Наконец, мы определяем фактический фон, создавая прямоугольный элемент с такими же размерами, как на поверхности рисования выше, и заполняем его только что созданным рисунком.

Заголовок

Теперь мы собираемся создать раздел заголовка:

 var headline = snap.paper.text(56,100, ['The Three Layers','of','Every Web Page']).attr({fill: '#FBAF3F', fontFamily: 'Impact'}); headline.select('tspan:first-of-type').attr({fontSize: '2.8em'}) headline.select('tspan:nth-of-type(2)').attr({fill: 'none', stroke: '#FBAF3F', fontSize: '2.2em', dx: '15px', dy: '5px'}); headline.select('tspan:last-of-type').attr({fontSize: '3.6em', x: '56px', y: '160px'}); 

Здесь переменная headline создает текстовый элемент. Обычно третий параметр в методе text() представляет собой одну строку, но нам нужен массив из нескольких текстовых строк.

Вот как Snap создает отдельный элемент tspan для каждой строки массива.

Делая это, мы получаем возможность стилизовать каждую текстовую строку независимо. В следующих трех строках мы используем CSS-селекторы, чтобы выбрать первую, вторую и третью части нашего заголовка и управлять ими по отдельности.

Мы используем атрибуты dx и dy (delta x и delta y), чтобы немного сместить вторую строку вправо и вниз. Третья строка позиционируется с использованием абсолютных атрибутов x и y .

Следующая вещь, которую мы создадим, — это набор прямоугольников, представляющих три слоя веб-страницы.

 var f_Shadow = snap.paper.filter(Snap.filter.shadow(-2, 4, 4)); var html_layer = snap.paper.rect(490,110, 200,30).attr({fill: '#00ADEF'}).transform('skewX(45)'); var css_layer = snap.paper.rect(500,100, 200,30).attr({fill: '#8CC63E', filter: f_Shadow}).transform('skewX(45)'); var js_layer = snap.paper.rect(510,90, 200,30).attr({fill: '#ED1C24', filter: f_Shadow}).transform('skewX(45)'); var underline = snap.paper.line(56,180, 856,180).attr({stroke: '#FBAF3F', strokeWidth: '5px'}); 

Нам понадобится теневой фильтр для имитации эффекта отбрасывания тени, поэтому мы создадим его в первой строке кода. Затем мы добавляем три прямоугольника и трансформируем их, чтобы они отображались так, как мы хотим. Кроме того, мы добавили теневой фильтр ко второму и третьему, что делает всю картину намного более реалистичной.

Наконец, мы добавляем подчеркивание, чтобы более четко отделить наш заголовок от раздела тела, который мы создадим только сейчас.

Тело

Первая часть этого раздела будет сеткой, которую мы будем использовать в качестве контейнера для размещения основных компонентов инфографики.

 // Grid var arrow = snap.paper.polygon([0,10, 4,10, 2,0, 0,10]).attr({fill: '#FFF'}).transform('r270'); var marker = arrow.marker(0,0, 10,10, 0,5); var grid_hl1 = snap.paper.line(56,380, 856,380).attr({stroke: '#FFF', strokeWidth: '2px'}); var grid_hl2 = grid_hl1.clone().transform('t0,200'); var grid_hl3 = grid_hl1.clone().transform('t0,400'); var grid_vl1 = snap.paper.line(256,200, 256,800).attr({stroke: '#FFF', strokeWidth: '2px', markerStart: marker}); var grid_vl2 = grid_vl1.clone().transform('t330,0'); 

Сначала нам нужно создать маркер, который нам понадобится для двух линий сетки. Мы определяем форму для маркера (треугольная стрелка). Затем во второй строке мы используем его как источник для фактического маркера.

Следующий блок кода создает сетку.

Мы добавляем первую горизонтальную линию, затем клонируем ее и переводим ее положение еще два раза. Это дает нам три горизонтальные линии.

Таким же образом мы создаем две вертикальные линии. Также мы добавляем маркер для каждого из них.

Мы хотим, чтобы маркер появлялся в начале строк, и по этой причине мы используем атрибут markerStart .

Мы ставим стрелки на вертикальные линии, чтобы служить подсказкой, что инфографику нужно исследовать снизу вверх.

 // Shapes var html_square = snap.paper.rect(96,620, 120,120).attr({fill: '#00ADEF', stroke: '#FFF', strokeWidth: '2px', filter: f_Shadow}); var html_square_text = snap.paper.text(110,693, 'HTML').attr({fill: '#FFF', fontFamily: 'Comic Sans MS', fontSize: '2em', fontWeight: 'bold'}); var css_circle = snap.paper.circle(156,480, 60).attr({fill: '#8CC63E', stroke: '#FFF', strokeWidth: '2px', filter: f_Shadow}); var css_circle_text = snap.paper.text(124,493, 'CSS').attr({fill: '#FFF', fontFamily: 'Comic Sans MS', fontSize: '2em', fontWeight: 'bold'}); var js_triangle = snap.paper.polygon([96,325, 216,325, 156,235]).attr({fill: '#ED1C24', stroke: '#FFF', strokeWidth: '2px', filter: f_Shadow}); var js_triangle_text = snap.paper.text(132,306, 'JS').attr({fill: '#FFF', fontFamily: 'Comic Sans MS', fontSize: '2em', fontWeight: 'bold'}); 

Теперь мы начнем заполнять продажи сетки. Мы начинаем с квадрата для нашего слоя HTML. Сначала мы создаем квадратную форму и добавляем к ней теневой фильтр. Затем мы создаем текстовый элемент и помещаем его внутрь фигуры. Мы закончим следующие фигуры таким же образом.

 // Ribbons &amp; Text Areas var html_ribbon = snap.paper.polygon([296,798, 546,798, 526,780, 546,762, 296,762, 316,780, 296,798]).attr({fill: '#00ADEF', filter: f_Shadow}); var css_ribbon = html_ribbon.clone().attr({fill: '#8CC63E'}).transform('t0,-200'); var js_ribbon = html_ribbon.clone().attr({fill: '#ED1C24'}).transform('t0,-400'); var html_ribbon_text = snap.paper.text(355,790, 'STRUCTURE').attr({fill: '#FFF', fontFamily: 'Comic Sans MS', fontSize: '1.4em'}); var css_ribbon_text = snap.paper.text(333,590, 'PRESENTATION').attr({fill: '#FFF', fontFamily: 'Comic Sans MS', fontSize: '1.4em'}); var js_ribbon_text = snap.paper.text(330,390, 'INTERACTIVITY').attr({fill: '#FFF', fontFamily: 'Comic Sans MS', fontSize: '1.4em'}); 

Мы переходим ко второму столбцу. Сначала мы создаем ленту с помощью .polygon() и снова добавляем теневой фильтр.

Затем мы клонируем ленту и переводим ее еще два раза, в результате получается три ленты, по одной для каждого слоя. Далее нам нужно добавить заголовки к лентам. Мы делаем это, создавая три текстовых элемента и размещая их в нужном месте.

 var html_textarea = snap.paper.text(300,630, ['HTML adds structure to a website\'s', 'content (text, images, and so on).', 'You can think of it as the anatomy', 'of the web pages.']).attr({fill: '#FFF', fontFamily: 'Trebuchet MS', fontStyle: 'italic'}); var css_textarea = snap.paper.text(300,430, ['CSS adds style to the content.', 'It makes the web page\'s components', 'to appear in different colors, sizes,', 'and so on.']).attr({fill: '#FFF', fontFamily: 'Trebuchet MS', fontStyle: 'italic'}); var js_textarea = snap.paper.text(300,230, ['JavaScript adds behavior', 'to the content. It makes the latter', 'responsive to user\'s actions.', 'Click the first post\'s image to see', 'an interactive example.']).attr({fill: '#FFF', fontFamily: 'Trebuchet MS', fontStyle: 'italic'}); var textareas = [html_textarea, css_textarea, js_textarea]; for (var i = 0; i &lt; textareas.length; i++) { textareas[i].selectAll('tspan').attr({x: '300px', dy: '1.2em'}); }; 

На этом этапе нам нужно объяснить, за что отвечает каждый слой и что он делает.

Итак, мы создаем три текстовых элемента с несколькими строками. Нам нужно, чтобы каждая строка отображалась в отдельной строке.

По этой причине мы помещаем элементы в массив, а затем используем цикл for для их итерации. Цикл состоит в том, чтобы выбрать все элементы tspan из каждого текстового элемента и сделать его атрибут x равным 300px , а также 300px каждую строку по вертикали на 1.2em .

Конечным результатом является то, что все строки, которые вы помещаете в определенный текстовый элемент, расположены правильно — все выровнены по левому краю, каждая отображается на отдельной строке, а расстояние между строками настроено правильно.

 // Wireframes var page = snap.paper.rect(610,400, 230,160).attr({fill: '#DFEDCC', filter: f_Shadow}); var logo = snap.paper.rect(625,410, 70,30).attr({fill: '#BDD1EC'}); var nav = snap.paper.line(620,450, 830,450).attr({stroke: '#652C90', strokeWidth: '6px', strokeDasharray: '25 5'}); var post_img = snap.paper.rect(625,464, 50,50).attr({fill: '#1B75BB'}); var post_txt = snap.paper.line(650,520, 650,550).attr({stroke: '#939597', strokeWidth: '50px', strokeDasharray: '3 7'}); var post = snap.paper.g(post_img, post_txt); var post_2 = post.clone().transform('t70,0'); var post_3 = post.clone().transform('t140,0'); 

В третьем столбце мы разместим каркас миниатюрной веб-страницы, цель которого — проиллюстрировать объяснения во втором столбце.

Сначала мы создаем новый прямоугольник для веб-страницы и добавляем к нему теневой фильтр. Затем мы создаем еще один прямоугольник для логотипа. Для навигации мы используем толстую пунктирную линию.

Далее мы создаем элементы, необходимые для наших сообщений ( post_img и post_txt ). Затем мы создаем первый пост, группируя вышеупомянутые элементы. Два других поста мы создаем путем клонирования первого и перевода его вправо.

Теперь у нас есть прототип, необходимый для наших каркасов.

 var f_Saturate = snap.paper.filter(Snap.filter.saturate(1)); var css_wireframe = snap.paper.g(page, logo, nav, post, post_2, post_3); var html_wireframe = css_wireframe.clone().transform('t0,200').attr({filter: f_Saturate}); var js_wireframe = css_wireframe.clone().transform('t0,-200'); 

На данный момент нам понадобится еще один фильтр, который мы создадим в первой строке. Затем мы используем элементы каркаса, которые мы только что создали, чтобы создать первый каркас.

Затем мы создаем второй каркас, клонируя первый, и добавляем к нему фильтр насыщения. Последние обесцвечивают цвета, чтобы показать, что HTML — это только структура без каких-либо стилей. И наконец, аналогичным образом создаем третий каркас.

 var panel = snap.paper.rect(650,200, 150,100, 3,3).attr({fill: '#1C98BA'}); var circle = snap.paper.circle(800,200, 10).attr({fill: '#1B75BB', stroke: '#DFEDCC', strokeWidth: '2px'}); var close_icon = snap.paper.text(796,204, 'x').attr({fill: '#FFF', fontFamily: 'Verdana'}); var close_button = snap.paper.g(circle, close_icon); var lightbox = snap.paper.g(panel, close_button).attr({opacity: 0}).insertBefore(js_wireframe); 

Здесь мы хотим создать лайтбокс с изображениями. Итак, начнем с прямоугольника с закругленными углами. Затем мы создаем форму круга и текст «X», который мы используем для создания кнопки закрытия, группируя их.

Наконец, мы заканчиваем лайтбокс, комбинируя панель и кнопку закрытия в группе, и делаем ее изначально невидимой. Кроме того, мы помещаем его за js_wireframe потому что в противном случае это будет мешать людям нажимать на сообщение.

 var ipost = js_wireframe.select('g:first-of-type&gt;rect').attr({fill: '#1B75BB'}) .mouseover(function(){ this.attr({fill: '#003EBA', cursor: 'pointer'}); }) .mouseout(function(){ this.attr({fill: '#1B75BB'}); }); ipost.click(function(){ lightbox.animate({transform: 't0,30', opacity: 1}, 400) .insertAfter(js_wireframe); }); 

Пришло время сделать вещи интерактивными. Для этого мы выбираем изображение (на самом деле, синий квадрат) из первого поста и заставляем его менять цвет при наведении курсора.

Затем мы добавляем прослушиватель событий щелчка, целью которого является отображение лайтбокса при нажатии на изображение первого сообщения.

 close_button.mouseover(function(){ this.attr({cursor: 'pointer'}); }).click(function(){ lightbox.animate({transform: 't0,0', opacity: 0}, 400, function(){ lightbox.insertBefore(js_wireframe); }); }); 

В приведенном выше коде мы делаем курсор таким же, как указатель, когда кнопка закрытия закрывается мышью; и когда щелкают, лайтбокс перемещается в исходное положение и исчезает.

Мы также добавляем функцию обратного вызова в метод js_wireframe animate() который помещает лайтбокс за js_wireframe после завершения анимации.

Наша последняя задача — добавить текст в нижний колонтитул. Но сначала нам нужно добавить следующий фрагмент ниже тега script (повторюсь: ниже тега script ):

 <!-- SVG Heart Shape --> <svg version="1.1" id="heart" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px" height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve"> <path fill-rule="evenodd" clip-rule="evenodd" fill="none" d="M11.995,6.243C8.888-2.079,0.057-0.138-0.001,9.521 c-0.032,5.305,4.205,7.288,7.026,9.408c2.736,2.057,4.683,4.87,4.988,6.068c0.261-1.173,2.43-4.066,4.962-6.125 c2.769-2.251,7.059-4.104,7.026-9.408C23.943-0.219,14.958-1.748,11.995,6.243z"/> </svg> 

Это код, который я получаю из файла SVG, созданного с помощью Adobe Illustrator.

 var footer_text = snap.paper.text(543,872, ['Made with','for SitePoint.com']).attr({fill: '#B5DD25', fontFamily: 'Comic Sans MS', fontSize: '1.2em'}); footer_text.select('tspan:nth-child(2)').attr({dx: '45px'}); Snap.select('#heart').appendTo(snap); Snap.select('path').attr({fill: '#EC008B', stroke: '#FFF'}).transform('t645,850').insertAfter(background); 

Вернувшись в тег script , мы создаем текстовый элемент, который состоит из двух строк, а затем 45px вторую строку на 45px с помощью атрибута dx .

Как вы уже заметили, наша инфографика немного смещена справа из-за кода SVG, который мы только что добавили.

Не беспокойся Мы исправим это через минуту.

Сначала мы выбираем фрагмент кода SVG, используя его атрибут id , и добавляем его к поверхности рисования. Затем мы выбираем путь сердца, делаем его обводку белым и заполняем его приятным розовым цветом.

Также мы меняем его положение, чтобы оно появлялось между двумя строками, и вставляем его после фона, чтобы сделать его видимым.

OK. Теперь все должно быть хорошо.

Вот рабочий кодекс нашей Snap Infographic в действии.

Открыть в новом окне

Резюме

Таким образом, я должен сказать, что даже с такой мощной библиотекой, как Snap, создание всей SVG-графики с нуля не так просто, как хотелось бы.

Нам все еще нужно много плановых и математических вычислений, чтобы получить правильный результат, который немного утомителен и требует много времени.

Конечно, Snap позволяет нам использовать и манипулировать существующим документом SVG (созданным с помощью Illustrator или Inkscape), но это выходит за рамки данного руководства.

Несмотря на это, я думаю, что окончательный результат определенно подтверждает наши усилия.