Синус и косинус в веб-дизайне

Влад Мержевич

В CSS добавились новые стилевые тригонометрические функции, такие как sin(), cos(), tan() и др. В физике, математике и программировании, понятно, тригонометрические функции востребованы и нужны для различных вычислений. Но где их можно применять в веб-дизайне? В итоге появление всяких синусов и косинусов вызвало недоумение у многих веб-разработчиков. Давайте разбираться, где и как их можно использовать на практике.

Для начала вспомним, что собой вообще представляют синус и косинус на примере прямоугольного треугольника (рис. 1).

Рис. 1. Прямоугольный треугольник

Синусом угла φ называется отношение противолежащего катета к гипотенузе.

sinφ= Противолежащий катет Гипотенуза = B C

Косинусом угла φ называется отношение прилежащего катета к гипотенузе.

cosφ= Прилежащий катет Гипотенуза = A C

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

Рис. 2. Точка на окружности

Используя определения синуса и косинуса получаем формулы для вычисления координат точки x и y.

  • x = R·cos φ
  • y = R·sin φ

В веб-дизайне отсчёт координат начинается от левого верхнего угла элемента, а угол φ считается от вертикальной оси (рис. 3). При этом радиус окружности у нас привязан к размерам элемента и всегда равен 50%. Это же касается и центра окружности, она всегда располагается в центре элемента и её координаты тоже равны 50%.

Рис. 3. Координаты относительно элемента

С учётом этого, наши формулы для вычисления координат видоизменятся.

  • x = x0 + R·sin φ = 50% + 50%·sin φ
  • y = y0 − R·cos φ = 50% − 50%·cos φ

В качестве примера рассмотрим работу этих формул при создании многоугольников. Для этого будем использовать свойство clip-path и стилевую функцию polygon(), которой следут передать координаты вершин. Например, треугольнику требуется передать координаты x и y трёх точек, разделяя их запятыми.

clip-path: polygon(x1 y1, x2 y2, x3 y3);

Углы φ для треугольника легко получить, если разделить 360 на 3 и отмерить полученное значение от нуля. В итоге:

φ1 = 0; φ2 = 120°; φ3 = 240°;

В качестве значения функции sin() можно использовать градусы, радианы или повороты — sin(120deg) или sin(0.33turn). В итоге, для треугольника координаты вершин будут следующими:

clip-path: polygon(
  calc(50% + 50% * sin(0)) calc(50% - 50% * cos(0)),
  calc(50% + 50% * sin(0.33turn)) calc(50% - 50% * cos(0.33turn)),
  calc(50% + 50% * sin(0.66turn)) calc(50% - 50% * cos(0.66turn)),
);

В примере 1 с помощью указанного подхода показано создание пятиугольника, внутри которого располагается фоновое изображение.

Пример 1. Создание пятиугольника

<!DOCTYPE html>
<html lang="ru">
 <head>
  <meta charset="utf-8">
  <title>Синус и косинус</title>
  <style>
   .poly {
    --s: 200px; /* Размер элемента */
    width: var(--s); /* Ширина */
    height: var(--s); /* Высота */
    background: url(image/html-256.png) no-repeat 50% 50% / cover; /* Фон */
    clip-path: polygon(
      calc(50% + 50% * sin(0))       calc(50% - 50% * cos(0)),
      calc(50% + 50% * sin(0.2turn)) calc(50% - 50% * cos(0.2turn)),
      calc(50% + 50% * sin(0.4turn)) calc(50% - 50% * cos(0.4turn)),
      calc(50% + 50% * sin(0.6turn)) calc(50% - 50% * cos(0.6turn)),
      calc(50% + 50% * sin(0.8turn)) calc(50% - 50% * cos(0.8turn))
    );
   }
  </style>
 </head>
 <body>
  <div class="poly"></div>
 </body>
</html>

Результат данного примера показан на рис. 4.

Рис. 4. Пятиугольник

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

  • Размер элемента меняется в единственном месте (переменная --s), все остальные значения вычисляются браузером самостоятельно. Это позволяет легко менять размеры, задавая их в пикселях или процентах и подстраивая размер фигуры под размеры контейнера.
  • Использование формул в CSS позволяет создавать различные эффекты на основе переходов и анимации.

Рассмотрим ещё один пример, где три иконки располагаются на окружности в вершинах невидимого треугольника (рис. 5).

Рис. 5. Расположение иконок на окружности

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

left: calc(50% + 50% * sin(var(--angle)));
top: calc(50% - 50% * cos(var(--angle)));

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

.user-icon-add   { --angle: 120deg; }

Поскольку свойства left и top отсчитываются от левого и верхнего краёв элемента, иконки надо будет сдвинуть влево и вверх на половину размера иконки. Функция translate() подходит для этого лучше всего.

transform: translate(-50%, -50%);

В примере 2 сделана простая анимация иконок при наведении на элемент. Сперва иконки располагаются в центре и невидимы, затем они «разбегаются» в разные стороны и встают на свои места.

Пример 2. Расположение иконок

<!DOCTYPE html>
<html lang="ru">
 <head>
  <meta charset="utf-8">
  <title>Синус и косинус</title>
  <style>
   .user {
    --W: 300px; /* Размер нашей области */
    --s_user: 100px; /* Размер картинки с пользователем */
    --s_icon: 60px; /* Размер иконок */
    width: var(--W); height: var(--W); /* Размеры элемента */
    border: 1px solid turquoise; /* Параметры рамки */
    border-radius: 50%; /* Радиус скругления */
    position: relative; /* Относительное позиционирование */
    margin: 2em; /* Добавляем пустое пространство вокруг */
   }
   .user-img {
    position: absolute; /* Абсолютное позиционирование */
    width: var(--s_user); height: var(--s_user); /* Размеры */
    left: calc(50% - var(--s_user) / 2); /* Располагаем по центру */
    top: calc(50% - var(--s_user) / 2); /* Располагаем по центру */
   }
   .user-icon {
    position: absolute; /* Абсолютное позиционирование */
    width: var(--s_icon); height: var(--s_icon); /* Размеры */
    left: 50%; top: 50%; /* Располагаем в центре */
    transform: translate(-50%, -50%); /* Сдвигаем на половину элемента */
    border-radius: 50%; /* Круглая иконка */
    padding: 0.5em; /* Расстояние от иконки до края */
    box-sizing: border-box; /* В размерах не учитываем padding */
    background-color: #e8edbc; /* Цвет фона */
    opacity: 0; /* Прозрачность */
    transition: 1s; /* Время перехода */
   }
   .user-icon:hover {
    background-color: tan; /* Цвет фона при наведении */
   }
   .user-icon-x     { --angle: 0deg;   }
   .user-icon-add   { --angle: 120deg; }
   .user-icon-minus { --angle: 240deg; }
   .user:hover .user-icon {
    left: calc(50% + 50% * sin(var(--angle)));
    top: calc(50% - 50% * cos(var(--angle)));
    opacity: 1; /* Иконка становится видимой */
   }
  </style>
 </head>
 <body>
  <div class="user">
   <div class="user-icons">
    <img src="image/user-x.svg" class="user-icon user-icon-x" alt="">
    <img src="image/user-add.svg" class="user-icon user-icon-add" alt="">
    <img src="image/user-minus.svg" class="user-icon user-icon-minus" alt="">
   </div>
   <img src="image/user-girl.svg" class="user-img" alt="">
  </div>
 </body>
</html>

Заключение

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

Не выкладывайте свой код напрямую в комментариях, он отображается некорректно. Воспользуйтесь сервисом cssdeck.com или jsfiddle.net, сохраните код и в комментариях дайте на него ссылку. Так и результат сразу увидят.