+102
-23
src/components/blog/Balloon.astro
+102
-23
src/components/blog/Balloon.astro
···
51
51
const maxtime = Number(el.dataset["maxTime"] ?? "0");
52
52
53
53
el.addEventListener("click", () => {
54
+
const cableParent = el.parentElement;
54
55
const postParent = el.parentElement?.parentElement;
56
+
if (!cableParent) throw new Error("No parent 1 level up!!!");
55
57
if (!postParent) throw new Error("No parent 2 levels up!!!");
56
58
console.log("clicked! popping", el, "with post", postParent);
57
59
58
60
el.blur();
59
61
60
-
el.animate(
61
-
[
62
+
Promise.all([
63
+
el.animate(
64
+
{ opacity: [1, 0] },
65
+
{
66
+
duration: 100,
67
+
fill: "forwards",
68
+
}
69
+
).finished,
70
+
71
+
cableParent.animate(
72
+
[
73
+
{},
74
+
{
75
+
height: 0,
76
+
top: 0,
77
+
},
78
+
],
79
+
{
80
+
duration: 500,
81
+
fill: "forwards",
82
+
}
83
+
),
84
+
85
+
postParent.animate(
86
+
[
87
+
{},
88
+
{
89
+
top: "calc(var(--x-offset-0) + 50rem)",
90
+
},
91
+
],
62
92
{
63
-
opacity: 1,
93
+
duration: 1000,
94
+
easing: "ease-in-out",
95
+
}
96
+
).finished,
97
+
]).then(() => {
98
+
const duration = (mintime + Math.random() * (maxtime - mintime)) * 1000;
99
+
100
+
el.animate(
101
+
{
102
+
opacity: [0, 1],
103
+
scale: [0, 1],
104
+
offset: [0, 1],
64
105
},
65
106
{
66
-
opacity: 0,
67
-
},
107
+
duration,
108
+
fill: "forwards",
109
+
// easing: "ease-in",
110
+
}
111
+
);
112
+
113
+
cableParent.animate(
114
+
[
115
+
{
116
+
height: 0,
117
+
top: 0,
118
+
},
119
+
{
120
+
height: "var(--length)",
121
+
top: "calc(-1 * var(--length))",
122
+
},
123
+
],
68
124
{
69
-
duration: 500,
70
-
},
71
-
],
72
-
{}
73
-
).finished.then(() =>
74
-
el.animate(
125
+
duration,
126
+
fill: "forwards",
127
+
}
128
+
);
129
+
130
+
postParent.animate(
75
131
[
76
-
{ opacity: 0, scale: 0 },
77
-
{ opacity: 1, offset: 0.001 },
78
-
{ scale: 1 },
132
+
{
133
+
top: "calc(var(--x-offset-0) + 50rem)",
134
+
},
135
+
{},
79
136
],
80
137
{
81
-
duration: (mintime + Math.random() * (maxtime - mintime)) * 1000,
82
-
easing: "ease-out",
138
+
duration,
139
+
fill: "forwards",
140
+
easing: "ease-in",
83
141
}
84
-
)
85
-
);
142
+
);
143
+
});
86
144
});
87
145
});
88
146
</script>
···
164
222
}
165
223
}
166
224
225
+
@keyframes bouncing {
226
+
from,
227
+
to {
228
+
scale: 1 1;
229
+
}
230
+
50% {
231
+
scale: 1.05 1.1;
232
+
}
233
+
}
234
+
167
235
.cable {
168
236
position: absolute;
169
237
170
238
width: 0.5rem;
171
239
height: var(--length);
240
+
border-radius: 0.25rem;
172
241
background: black;
242
+
243
+
[data-time="night"] + * & {
244
+
background: #404040;
245
+
}
173
246
174
247
/* .5rem accounts for border (z-index doesn't work) */
175
248
z-index: -99;
···
204
277
animation: infinite var(--timing) linear inv-tilt;
205
278
}
206
279
207
-
transition: scale 0.2s;
208
-
209
280
&:focus {
210
-
outline: none;
211
-
scale: 1.1;
281
+
@media (prefers-reduced-motion: no-preference) {
282
+
outline: none;
283
+
animation:
284
+
infinite var(--timing) linear inv-tilt,
285
+
infinite 2s cubic-bezier(0.8, -0.4, 0.469, 1.692) bouncing;
286
+
}
212
287
}
213
288
}
214
289
···
222
297
translate: -50%;
223
298
z-index: 1;
224
299
300
+
border-radius: 0.25rem;
225
301
background-color: black;
226
-
border-radius: 0.25rem;
302
+
303
+
[data-time="night"] + * & {
304
+
background: #404040;
305
+
}
227
306
}
228
307
229
308
.tie {