Как я вспоминал школьный курс геометрии

в 11:30, , рубрики: css, css3, html, html5, less, Блог компании Netcracker

image

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

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

image

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

http://codepen.io/belyan/pen/vymwXe

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

image

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

Попробуем применить другую, чуть менее известную технику создания треугольников в CSS. Опять воспользуемся бордерами, только сделаем треугольник в левом верхнем углу, добавим элементу тень и сдвинем ее в тот же угол с помощью отрицательных значений. Теперь повернем элемент на 45 градусов по часовой стрелке — и получим треугольник с тенью.

image

http://codepen.io/belyan/pen/ObmYQa

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

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

image

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

Пишем миксин

Далее я буду использовать препроцессор LESS, но данный миксин можно легко переписать и на SCSS.

Возьмем в качестве иллюстрации вот такой треугольник и зададим в качестве начальных параметров его размеры — основание b и высоту h.

image

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

@base: 100px;
@height: 100px;
@side: sqrt(@base * @base / 4 + @height * @height); // про штаны, надеюсь, все помнят ;)

Зная значения всех сторон, мы можем найти боковой угол alpha. Вспоминаем, что синус угла есть отношение противолежащего катета к гипотенузе. Противолежащий катет у нас h, а гипотенуза — a. Таким образом:

@alpha: asin(@height / @side); // результат будет в радианах!

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

image

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

@beta: convert(@alpha, deg) - 45deg; // не забываем перевести радианы обратно в градусы

Последнее значение, которое нам необходимо вычислить, — это боковая сторона квадрата до его трансформации. Для этого воспользуемся косинусом угла. Угол наклона нам известен, а прилежащим катетом будет являться сторона a. Таким образом, боковую сторону можно вычислить по формуле:

@size: @side * cos(@beta);

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

http://codepen.io/belyan/pen/wozWXE

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

http://codepen.io/belyan/pen/LbyKEd

Хочу добавить, что с помощью этого же миксина мы можем создавать и равносторонние треугольники, поскольку они являются частным случаем равнобедренных. В этом случае нам достаточно будет задать только основание треугольника, а его высоту можно легко вычислить по формуле:
@height: @base * sin(60deg);.

Также можно добавить в миксин возможность задания направления вершины треугольника: top, left, right, bottom. Я не стал этого делать в статье, поскольку объем кода существенно увеличился бы. Тем же, кому интересна эта тема, предлагаю взглянуть на расширенную версию данного миксина. Там же вы найдете миксины и для других геометрических фигур, таких как круг, овал, крест, звезда и пр.

http://codepen.io/belyan/pen/Lpqdmx

Надеюсь, вам было интересно. Спасибо за внимание!

Автор: Netcracker

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js