Получить ответ по завершению
14.01.2022, 21:14. Показов 707. Ответов 2
Ребят я в js вообще ноль, знаю то что плохо и т.д. я больше по php, я скачал колесо формуты, написан на html, css, js мне теперь надо по завершению получить ответ, что выйграл пользователь, что бы отправить купон ему на почту, но я не знаю как, и как мне вставить по середине логотип?
| HTML5 | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| <!DOCTYPE html>
<html lang="ru" >
<head>
<meta charset="UTF-8">
<title>Колесо удачи</title>
<!-- используем всю ширину экрана -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- подключаем стили -->
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- главный блок -->
<div class="deal-wheel">
<!-- блок с призами -->
<ul class="spinner"></ul>
<!-- язычок барабана -->
<div class="ticker"></div>
<!-- кнопка -->
<button class="btn-spin">Испытай удачу</button>
</div>
<!-- подключаем скрипт -->
<script src="script.js"></script>
</body>
</html> |
|
| JavaScript | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
| // надписи и цвета на секторах
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 wheel = document.querySelector(".deal-wheel");
const spinner = wheel.querySelector(".spinner");
const trigger = wheel.querySelector(".btn-spin");
const ticker = wheel.querySelector(".ticker");
// на сколько секторов нарезаем круг
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);
// переменная для анимации
let tickerAnim;
// угол вращения
let rotation = 0;
// текущий сектор
let currentSlice = 0;
// переменная для текстовых подписей
let prizeNodes;
// расставляем текст по секторам
const createPrizeNodes = () => {
// обрабатываем каждую подпись
prizes.forEach(({ text, color, reaction }, i) => {
// каждой из них назначаем свой угол поворота
const rotation = ((prizeSlice * i) * -1) - prizeOffset;
// добавляем код с размещением текста на страницу в конец блока spinner
spinner.insertAdjacentHTML(
"beforeend",
// текст при этом уже оформлен нужными стилями
`<li class="prize" data-reaction=${reaction} style="--rotate: ${rotation}deg">
<span class="text">${text}</span>
</li>`
);
});
};
// рисуем разноцветные секторы
const createConicGradient = () => {
// устанавливаем нужное значение стиля у элемента spinner
spinner.setAttribute(
"style",
`background: conic-gradient(
from -90deg,
${prizes
// получаем цвет текущего сектора
.map(({ color }, i) => `${color} 0 ${(100 / prizes.length) * (prizes.length - i)}%`)
.reverse()
}
);`
);
};
// создаём функцию, которая нарисует колесо в сборе
const setupWheel = () => {
// сначала секторы
createConicGradient();
// потом текст
createPrizeNodes();
// а потом мы получим список всех призов на странице, чтобы работать с ними как с объектами
prizeNodes = wheel.querySelectorAll(".prize");
};
// определяем количество оборотов, которое сделает наше колесо
const spinertia = (min, max) => {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
};
// функция запуска вращения с плавной остановкой
const runTickerAnimation = () => {
// взяли код анимации отсюда: https://css-tricks.com/get-value-of-css-rotation-through-javascript/
const values = spinnerStyles.transform.split("(")[1].split(")")[0].split(",");
const a = values[0];
const b = values[1];
let rad = Math.atan2(b, a);
if (rad < 0) rad += (2 * Math.PI);
const angle = Math.round(rad * (180 / Math.PI));
const slice = Math.floor(angle / prizeSlice);
// анимация язычка, когда его задевает колесо при вращении
// если появился новый сектор
if (currentSlice !== slice) {
// убираем анимацию язычка
ticker.style.animation = "none";
// и через 10 миллисекунд отменяем это, чтобы он вернулся в первоначальное положение
setTimeout(() => ticker.style.animation = null, 10);
// после того, как язычок прошёл сектор - делаем его текущим
currentSlice = slice;
}
// запускаем анимацию
tickerAnim = requestAnimationFrame(runTickerAnimation);
};
// функция выбора призового сектора
const selectPrize = () => {
const selected = Math.floor(rotation / prizeSlice);
prizeNodes[selected].classList.add(selectedClass);
};
// отслеживаем нажатие на кнопку
trigger.addEventListener("click", () => {
// делаем её недоступной для нажатия
trigger.disabled = true;
// задаём начальное вращение колеса
rotation = Math.floor(Math.random() * 360 + spinertia(2000, 5000));
// убираем прошлый приз
prizeNodes.forEach((prize) => prize.classList.remove(selectedClass));
// добавляем колесу класс is-spinning, с помощью которого реализуем нужную отрисовку
wheel.classList.add(spinClass);
// через CSS говорим секторам, как им повернуться
spinner.style.setProperty("--rotate", rotation);
// возвращаем язычок в горизонтальную позицию
ticker.style.animation = "none";
// запускаем анимацию вращение
runTickerAnimation();
});
// отслеживаем, когда закончилась анимация вращения колеса
spinner.addEventListener("transitionend", () => {
// останавливаем отрисовку вращения
cancelAnimationFrame(tickerAnim);
// получаем текущее значение поворота колеса
rotation %= 360;
// выбираем приз
selectPrize();
// убираем класс, который отвечает за вращение
wheel.classList.remove(spinClass);
// отправляем в CSS новое положение поворота колеса
spinner.style.setProperty("--rotate", rotation);
// делаем кнопку снова активной
trigger.disabled = false;
});
// подготавливаем всё к первому запуску
setupWheel(); |
|
| CSS | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
| /* делаем везде так, чтобы свойства width и height задавали не размеры контента, а размеры блока */
* {
box-sizing: border-box;
}
/* общие настройки страницы */
body {
/* подключаем сетку */
display: grid;
/* ставим всё по центру */
place-items: center;
/* если что-то не помещается на своё место — скрываем то, что не поместилось */
overflow: hidden;
}
/* общий блок для всех элементов */
.deal-wheel {
/* задаём переменные блока */
/* размеры колеса */
--size: clamp(250px, 80vmin, 700px);
/* настройки яркости и заливки фона секторов */
--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;
/* подключаем сетку */
display: grid;
grid-gap: calc(var(--size) / 20);
/* выравниваем содержимое блока по центру */
align-items: center;
/* задаём имена областей внутри сетки */
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;
}
/* сектор колеса */
.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;
}
/* язычок */
.ticker {
/* добавляем относительное позиционирование */
position: relative;
/* устанавливаем размеры */
left: calc(var(--size) / -15);
width: calc(var(--size) / 10);
height: calc(var(--size) / 20);
/* фон язычка */
background: var(--lg);
/* делаем так, чтобы язычок был выше колеса */
z-index: 1;
/* форма язычка */
clip-path: polygon(20% 0, 100% 50%, 20% 100%, 0% 50%);
/* устанавливаем точку, относительно которой будет вращаться язычок при движении колеса */
transform-origin: center left;
}
/* кнопка запуска колеса */
.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;
}
/* анимация вращения */
.is-spinning .spinner {
transition: transform 8s cubic-bezier(0.1, -0.01, 0, 1);
}
/* анимация движения язычка */
.is-spinning .ticker {
animation: tick 700ms cubic-bezier(0.34, 1.56, 0.64, 1);
}
/* эффект, когда колесо задевает язычок при вращении */
@keyframes tick {
40% {
/* чуть поворачиваем язычок наверх в середине анимации */
transform: rotate(-12deg);
}
}
/* анимируем выпавший сектор */
.prize.selected .text {
/* делаем текст белым */
color: white;
/* настраиваем длительность анимации */
animation: selected 800ms ease;
}
/* настраиваем анимацию текста на выпавшем секторе по кадрам */
@keyframes selected {
/* что происходит на 25% от начала анимации */
25% {
/* увеличиваем текст в 1,25 раза */
transform: scale(1.25);
/* добавляем тексту тень */
text-shadow: 1vmin 1vmin 0 hsla(0 0% 0% / 0.1);
}
40% {
transform: scale(0.92);
text-shadow: 0 0 0 hsla(0 0% 0% / 0.2);
}
60% {
transform: scale(1.02);
text-shadow: 0.5vmin 0.5vmin 0 hsla(0 0% 0% / 0.1);
}
75% {
transform: scale(0.98);
}
85% {
transform: scale(1);
}
} |
|
0
|