-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
203 lines (170 loc) · 8.12 KB
/
index.html
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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
margin: 0;
padding: 0;
width: 100vw;
height: 100vh;
overflow: hidden;
}
.wheel {
width: 300px;
height: 200px;
/* background-color: blue; */
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.card {
/* width: 90px;
height: 50px;
background-color: red; */
width: 200px;
height: 200px;
border-radius: 100px;
box-shadow: 10px 10px 8px black;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
font-size: 2.5em;
}
</style>
</head>
<body>
<div class="wheel">
<img src="https://picsum.photos/1000/1200" class="card">
<img src="https://picsum.photos/1000/1100" class="card">
<img src="https://picsum.photos/1000/1300" class="card">
<img src="https://picsum.photos/1000/1400" class="card">
<img src="./icon-round-1080.png" class="card" style="box-shadow: none;">
<img src="https://picsum.photos/1000/1150" class="card">
<img src="https://picsum.photos/1000/1350" class="card">
<img src="https://picsum.photos/1000/1450" class="card">
<!-- <div class="card">0</div>
<div class="card">1</div>
<div class="card">2</div>
<div class="card">3</div>
<div class="card">4</div>
<div class="card">5</div>
<div class="card">6</div>
<div class="card">7</div> -->
</div>
<script>
let theta = Math.PI / 4.0;
let new_theta = 0.0;
let new_x = 0.0;
let new_y = 0.0;
let wheel_radius = 200.00;
let wheel_theta = 0.0;
const cards = document.querySelectorAll('.card');
const wheel = document.querySelector('.wheel');
const center = {
x: parseFloat(getComputedStyle(cards[0]).left),
y: parseFloat(getComputedStyle(cards[0]).top)
}
cards.forEach((card, index) => {
new_theta = theta * index;
new_x = (Math.cos(new_theta) * wheel_radius);
new_y = (-1.0 * Math.sin(new_theta) * wheel_radius);
// place the cards on the wheel
card.style.left = `${center.x + new_x}px`;
card.style.top = `${center.y + new_y}px`;
});
let wheel_in_progress = false;
let snap_in_progress = false;
document.addEventListener('wheel', event => {
if (snap_in_progress) {
return;
} else {
clearTimeout(wheel_in_progress);
// let scroll_speed = event.deltaY * 0.002;
let scroll_speed = (event.deltaY / 360) * 20;
wheel_theta = wheel_theta + scroll_speed;
wheel.style.transitionDelay = '0.0s';
wheel.style.transitionDuration = '0.0s';
wheel.style.transform = `translate(-50%, -50%) rotate(${wheel_theta}deg)`;
// rotate each card in the opposite direction of the spin in order to maintain equilibrium
cards.forEach(card => {
card.style.transitionDelay = '0.0s';
card.style.transitionDuration = '0.0s';
card.style.transform = `translate(-50%, -50%) rotate(${-1.0 * wheel_theta}deg)`;
});
wheel_in_progress = setTimeout(() => {
snap_back();
}, 100)
}
});
const center_of_wheel = {
x: parseFloat(getComputedStyle(wheel).left),
y: parseFloat(getComputedStyle(wheel).top)
}
const snap_point = {
x: cards[2].getBoundingClientRect().x + 100,
y: cards[2].getBoundingClientRect().y + 100
}
snap_point.theta = Math.atan2(Math.abs(snap_point.y - center_of_wheel.y), Math.abs(snap_point.x - center_of_wheel.x));
snap_point.theta = snap_point.theta * (180 / Math.PI);
function snap_back() {
snap_in_progress = true;
let shortest_distance = Math.pow(((cards[3].getBoundingClientRect().x + 100) - snap_point.x), 2) + Math.pow(((cards[3].getBoundingClientRect().y + 100) - snap_point.y), 2);
shortest_distance = Math.sqrt(shortest_distance);
let closest_card = null;
// loop through all cards and compare distances to snap_point; find shortest distance
cards.forEach((card, index) => {
let dx = (card.getBoundingClientRect().x + 100) - snap_point.x;
let dy = (card.getBoundingClientRect().y + 100) - snap_point.y;
let current_distance = Math.pow(dx, 2) + Math.pow(dy, 2);
current_distance = Math.sqrt(current_distance)
if (shortest_distance >= current_distance) {
shortest_distance = current_distance;
closest_card = card;
}
});
// find angle between snap_point's theta and closest_card's theta
let closest_cards_x = closest_card.getBoundingClientRect().x + 100;
let closest_cards_y = closest_card.getBoundingClientRect().y + 100;
let closest_cards_theta = Math.atan2(Math.abs(closest_cards_y - center_of_wheel.y), Math.abs(closest_cards_x - center_of_wheel.x));
closest_cards_theta = closest_cards_theta * (180 / Math.PI);
let theta_between = Math.abs(closest_cards_theta - snap_point.theta);
// decide whether to make a positive or negative degree shift
if (closest_cards_x > center_of_wheel.x && closest_cards_y <= center_of_wheel.y) { // QI
theta_between = closest_cards_theta > snap_point.theta ? theta_between : -1.0 * theta_between;
} else if (closest_cards_x <= center_of_wheel.x && closest_cards_y <= center_of_wheel.y) { // QII
theta_between = closest_cards_theta > snap_point.theta ? -1.0 * theta_between : theta_between;
} else if (closest_cards_x <= center_of_wheel.x && closest_cards_y > center_of_wheel.y) { // QIII
theta_between = closest_cards_theta > snap_point.theta ? theta_between : -1.0 * theta_between;
} else if (closest_cards_x > center_of_wheel.x && closest_cards_y >= center_of_wheel.y) { // QIV
theta_between = closest_cards_theta > snap_point.theta ? -1.0 * theta_between : theta_between;
}
// rotate wheel towards snap point
wheel.style.transitionDelay = '0.1s';
wheel.style.transitionDuration = '1.0s';
wheel.style.transform = `translate(-50%, -50%) rotate(${wheel_theta + theta_between}deg)`;
// rotate cards in opposite direction of wheel to maintain equilibrium
cards.forEach(card => {
card.style.transitionDelay = '0.1s';
card.style.transitionDuration = '1.0s'
if (closest_card == card) { // make the card in focus larger and overlap others
card.style.transform = `translate(-50%, -50%) rotate(${-1.0 * (wheel_theta + theta_between)}deg) scale(1.0)`;
card.style.zIndex = 100;
} else {
card.style.transform = `translate(-50%, -50%) rotate(${-1.0 * (wheel_theta + theta_between)}deg) scale(0.5)`;
card.style.zIndex = 1;
}
});
// keep track of the amount of theta the wheel rotated
wheel_theta = wheel_theta + theta_between;
setTimeout(() => {
snap_in_progress = false;
}, 200);
}
</script>
</body>
</html>