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

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

Проблема

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

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

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

 

Решение

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

Но это не только ужасно грязный трюк, он вдобавок непомерно раздувает код и добавляет на страницу десятки DOM-элементов, не имеющих практической ценности. Идеального способа достичь желаемого результата с помощью чистого CSS не существует, но мы можем с легкостью создавать подобные дизайны, используя немного  строкового SVG.

Формат SVG всегда поддерживал отображение текста вдоль любого пути, а дуги окружности — это всего лишь один из вариантов формы пути. Почему бы не попробовать? Простейший способ нарисовать текст по кругу с помощью SVG — поместить его в элемент  <textPath> внутри элемента  <text> . Элемент  <textPath> также ссылается на элемент  <path> , определяя форму пути по его идентификатору.

Текст внутри строкового SVG также наследует большую часть стилизации шрифтов (за исключением  line-height , так как это в SVG задается вручную), поэтому, в отличие от решений, включающих внешние изображения в формате SVG, в данном случае о стилях можно не беспокоиться. Предположим, мы хотим вывести фразу circular reasoning works because по кругу, чтобы она формировала замкнутую окружность, как на рисунке.

Читайте также  Как корректировать величину табуляции на css


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

Читайте также  Лигатуры в CSS

 

Мы добавляем текст с помощью элементов  <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

 

 

 

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Плюсануть
Поделиться

Об авторе

admin administrator

Сообщить об опечатке

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