/* делаем везде так, чтобы свойства width и height задавали не размеры контента, а размеры блока */
* {
box-sizing: border-box;
}
/* общие настройки страницы */
body {
/* подключаем сетку */
display: grid;
/* ставим всё по центру */
place-items: center;
/* если что-то не помещается на своё место — скрываем то, что не поместилось */
overflow: hidden;
}
/* общий блок для всех элементов */
.deal-wheel {
/* задаём переменные блока, внутри которого всё будет рисоваться */
/* размеры колеса */
--size: clamp(250px, 80vmin, 700px);
/* clamp — функция CSS, которая задаёт три размера: минимальное, предпочтительное и максимальное. В данном случае мы хотим, чтобы колесо было не меньше 250 пикселей, не больше 700 пикселей, но в идеале — 80% от безопасно малой высоты окна браузера */
/* настройки яркости и заливки фона секторов. Нам понадобится описать поведение градиента, это у нас делается через много переменных */
--lg-hs: 0 3%;
--lg-stop: 50%;
--lg: linear-gradient(
hsl(var(--lg-hs) 0%) 0 var(--lg-stop),
hsl(var(--lg-hs) 20%) var(--lg-stop) 100%
);
/* добавляем позиционирование относительно других элементов */
position: relative;
/* подключаем стандартную CSS-сетку */
display: grid;
grid-gap: calc(var(--size) / 20);
/* выравниваем содержимое блока по центру */
align-items: center;
/* задаём имена областей внутри сетки — в CSS теперь можно прямо назвать эти области */
grid-template-areas:
"spinner"
"trigger";
/* устанавливаем размер шрифта */
font-size: calc(var(--size) / 21);
}
/* всё, что относится ко внутренним элементам главного блока, будет находиться в области сетки с названием spinner */
.deal-wheel > * {
grid-area: spinner;
}
/* сам блок и кнопка будут находиться в области сетки с названием trigger и будут выровнены по центру */
.deal-wheel .btn-spin {
grid-area: trigger;
justify-self: center;
}
// надписи и цвета на секторах
const prizes = [
{
text: "Скидка 10%",
color: "hsl(197 30% 43%)",
},
{
text: "Дизайн в подарок",
color: "hsl(173 58% 39%)",
},
{
text: "Второй сайт бесплатно",
color: "hsl(43 74% 66%)",
},
{
text: "Скидка 50%",
color: "hsl(27 87% 67%)",
},
{
text: "Блог в подарок",
color: "hsl(12 76% 61%)",
},
{
text: "Скидок нет",
color: "hsl(350 60% 52%)",
},
{
text: "Таргет в подарок",
color: "hsl(91 43% 54%)",
},
{
text: "Скидка 30% на всё",
color: "hsl(140 36% 74%)",
}
];
// на сколько секторов нарезаем круг
const prizeSlice = 360 / prizes.length;
// на какое расстояние смещаем сектора друг относительно друга
const prizeOffset = Math.floor(180 / prizes.length);
// прописываем CSS-классы, которые будем добавлять и убирать из стилей
const spinClass = "is-spinning";
const selectedClass = "selected";
// получаем все значения параметров стилей у секторов
const spinnerStyles = window.getComputedStyle(spinner);
// расставляем текст по секторам
const createPrizeNodes = () => {
// обрабатываем каждую подпись
prizes.forEach(({ text, color, reaction }, i) => {
// каждой из них назначаем свой угол поворота
const rotation = ((prizeSlice * i) * -1) - prizeOffset;
// добавляем код с размещением текста на страницу в конец блока spinner
spinner.insertAdjacentHTML(
"beforeend",
// текст при этом уже оформлен нужными стилями
`
${text}
`
);
});
};
// рисуем разноцветные секторы
const createConicGradient = () => {
// устанавливаем нужное значение стиля у элемента spinner
spinner.setAttribute(
"style",
`background: conic-gradient(
from -90deg,
${prizes
// получаем цвет текущего сектора
.map(({ color }, i) => `${color} 0 ${(100 / prizes.length) * (prizes.length - i)}%`)
.reverse()
}
);`
);
};
/* сектор колеса */
.spinner {
/* добавляем относительное позиционирование */
position: relative;
/* подключаем сетку */
display: grid;
/* выравниваем всё по центру */
align-items: center;
/* добавляем элемент в сетку */
grid-template-areas: "spinner";
/* устанавливаем размеры */
width: var(--size);
height: var(--size);
/* поворачиваем элемент */
transform: rotate(calc(var(--rotate, 25) * 1deg));
/* рисуем круглую обводку, а всё, что не поместится, — будет скрыто за кругом */
border-radius: 50%
};
/* всё, что внутри этого блока, будет находиться в области сетки с названием spinner */
.spinner * {
grid-area: spinner;
}
/* текст на секторах */
.prize {
/* включаем «гибкую» вёрстку */
display: flex;
align-items: center;
/* задаём отступы от краёв блока */
padding: 0 calc(var(--size) / 6) 0 calc(var(--size) / 20);
/* устанавливаем размеры */
width: 50%;
height: 50%;
/* устанавливаем координаты, относительно которых будем вращать текст */
transform-origin: center right;
/* поворачиваем текст */
transform: rotate(var(--rotate));
/* запрещаем пользователю выделять мышкой текст на секторах */
user-select: none;
}
/* кнопка запуска колеса */
.btn-spin {
color: white;
background: black;
border: none;
/* берём размер шрифта такой же, как в колесе */
font-size: inherit;
/* добавляем отступы от текста внутри кнопки */
padding: 0.9rem 2rem 1rem;
/* скругляем углы */
border-radius: 0.5rem;
/* меняем внешний вид курсора над кнопкой на руку*/
cursor: pointer;
}
/* если кнопка нажата и неактивна */
.btn-spin:disabled {
/* меняем внешний вид курсора */
cursor: progress;
/* делаем кнопку полупрозрачной */
opacity: 0.25;
}