Как сделать текст по кругу

Оцените материал
(0 голосов)

Проблема

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


Решение

Есть несколько сценариев, помогающих решить эту задачу. Принцип их работы заключается в том, что каждая буква оборачивается в отдельный элемент  <span> и эти элементы по отдельности поворачиваются, что позволяет сформировать окружность. Но это не только ужасно грязный трюк, он вдобавок непомерно раздувает код и добавляет на страницу десятки DOM-элементов, не имеющих практической ценности. Идеального способа достичь желаемого результата с помощью чистого CSS не существует, но мы можем с легкостью создавать подобные дизайны, используя немного  строкового SVG. Формат SVG всегда поддерживал отображение текста вдоль любого пути, а дуги окружности — это всего лишь один из вариантов формы пути. Почему бы не попробовать? Простейший способ нарисовать текст по кругу с помощью SVG — поместить его в элемент  <textPath> внутри элемента  <text> . Элемент  <textPath> также ссылается на элемент  <path> , определяя форму пути по его идентификатору. Текст внутри строкового SVG также наследует большую часть стилизации шрифтов (за исключением  line-height , так как это в SVG задается вручную), поэтому, в отличие от решений, включающих внешние изображения в формате SVG, в данном случае о стилях можно не беспокоиться. Предположим, мы хотим вывести фразу circular reasoning works because по кругу, чтобы она формировала замкнутую окружность, как на рисунке.


Начнем с добавления строкового SVG внутри на шего элемента HTML, а также с определения пути, описывающего окружность: к сожалению, <textPath> работает только с элементами <path>, поэтому для создания нашей окружности у нас не получится использовать гораздо более понятные элемент <circle>.
SVG
<div class="circular">
<svg viewBox="0 0 100 100">
<path d="M 0,50 a 50,50 0 1,1 0,1 z"
id="circle" />
</svg>
</div>
Обратите внимание, что мы определили габариты посредством  viewBox , а не с помощью атрибутов  width и  height . Это позволяет настраивать систему координат и соотношение сторон рисунка, вместо того чтобы всегда использовать четко определенный размер. Так не только намного компактнее; это экономит несколько строк CSS-кода, поскольку нам больше не приходится определять равную 100% ширину и высоту для элемента  <svg> — он сам подстраивается под размер своего контейнера. Если вы не понимаете синтаксис пути, не беспокойтесь. Его вообще мало кто понимает, и даже те, кто был посвящен в таинство синтаксиса пути в SVG, чаще всего забывают о нем в течение нескольких минут. Если вам интересно, то вот три команды, которые включает этот невероятно загадочный синтаксис:
‰ M 0,50 : перейти в точку (0,50);
‰ a 50,50 0 1,1 0,1 : нарисовать дугу из точки, в которой вы находитесь в данный момент, в точку, которая находится на  0 единиц правее и на  1 единицу ниже вашей текущей позиции. Радиус этой дуги равен  50 , как по горизонтали, так и по вертикали. Из двух возможных углов выбрать  наибольший и из двух возможных дуг выбрать ту, что находится справа от двух точек, а не слева;
‰ z : закрыть путь прямым отрезком.
Пока что наш путь представляет собой всего лишь черную окружность.

Мы добавляем текст с помощью элементов  <text> и  <textPath> и связываем его с нашей окружностью посредством свойства  xlink:href , как в следующем фрагменте кода:
SVG
<div class="circular">
<svg viewBox="0 0 100 100">
<path d="M 0,50 a 50,50 0 1,1 0,1 z"
id="circle" />
<text><textPath xlink:href="#circle">
circular reasoning works because
</textPath></text>
</svg>
</div>
Как видно на рисунке, хотя нам предстоит еще немало потрудиться, чтобы сделать этот текст привлекательным и читабельным, мы уже достигли результата, которого с помощью чистого CSS не сумели бы добиться и за миллион лет!

Следующим шагом будет удаление черной заливки из нашего кругового пути. Мы вообще не хотим, чтобы какая-либо часть нашей окружности была видна; ее единственное предназначение — служить направляющей для нашего текста. Этого можно добиться несколькими разными способами: например, поместив наш контур в элемент  <defs> (придуманный как раз для этой цели). Однако при создании нашего эффекта мы хотим минимизировать объем SVG-разметки, поэтому применим решение из CSS, а именно  fill: none: .circular path { fill: none; } Теперь, когда черный круг исчез, мы можем внимательнее изучить остальные недостатки. Самая большая проблема заключается в том, что большая часть текста находится за пределами SVG-элемента и обрезается им. Чтобы исправить этот дефект, нужно сделать контейнер меньше и применить к SVG-элементу  overflow: visible, чтобы он не обрезал никакое содержимое за пределами своего окна просмотра:
.circular {
width: 30em;
height: 30em;
}
.circular svg {
display: block;
overflow: visible;
}
Результат вы видите на рисунке. Это почти то, что нам нужно, но часть текста все равно обрезается.

Причина в том, что на обтекание влияют только габаритные размеры SVG-элемента, но не то, насколько содержимое выходит за пределы окна просмотра. Следовательно, тот факт, что какой-то текст переливается через края контейнера, создаваемого элементом  <svg> , не заставляет этот SVG-элемент сдвинуться вниз. Нам придется сделать это вручную, с помощью поля:
.circular {
width: 30em;
height: 30em;
margin: 3em auto 0;
}
.circular svg {
display: block;
overflow: visible;
}
Вот и все! Результат выглядит в точности как на рисунке выше, и распознавание текста программами чтения экрана проходит без сложностей. Если у нас только один фрагмент текста, нарисованного вдоль дуги окружности (скажем, на логотипе веб-сайта), то работа закончена. Но если нужно  применить подобную стилизацию к нескольким элементам на странице, то хотелось бы избежать повторения всей этой разметки SVG. Для чего можно написать короткий сценарий, который будет автоматически генерировать необходимые SVG-элементы, встречая в разметке нечто подобное:
HTML
<div class="circular">
circular reasoning works because
</div>

Наш код будет проходить по всем элементам с классом  circular , удаляя их текст и сохраняя его в переменной, а также добавляя необходимые SVG-элементы:

JS
$$('.circular').forEach(function(el) {
var NS = "http://www.w3.org/2000/svg";
var xlinkNS = "http://www.w3.org/1999/xlink";
var svg = document.createElementNS(NS, "svg");
var circle = document.createElementNS(NS, "path");
var text = document.createElementNS(NS, "text");
var textPath = document.createElementNS(NS, "textPath");
svg.setAttribute("viewBox", "0 0 100 100");
circle.setAttribute("d", "M0,50 a50,50 0 1,1 0,1z");
circle.setAttribute("id", "circle");
textPath.textContent = el.textContent;
textPath.setAttributeNS(xlinkNS, "xlink:href", "#circle");
text.appendChild(textPath);
svg.appendChild(circle);
svg.appendChild(text);
el.textContent = '';
el.appendChild(svg);
});

ПОПРОБУЙТЕ САМИ!
http://play.csssecrets.io/circular-text

Десерт на сегодня - видео, которое снял квадрокоптер, пролетая над статей дельфинов:

Прочитано 243 раз Последнее изменение Воскресенье, 23 апреля 2017 12:12
Другие материалы в этой категории:
Понравилась запись? Подпишитесь на обновления по почте:

Wix.com INT

TemplateMonster

Поиск по сайту

Kwork

Google+