mirror of
https://github.com/tiennm99/tiennm99bot.git
synced 2026-10-11 03:13:46 +00:00
fix(gacha): stop the card text moving after the card settles
Three things moved the text once the card looked still: - The spin's last degrees: Chrome draws text on a slightly tilted card differently from a flat one, so glyphs hopped as the spin ran out. The spin now lands flat a moment before the card stops gliding. - The landing: the card flew at its rounded size scaled to a fractional layout size, then was laid out again, shifting the text. The card's size is now whole pixels. - The last flight frames: a sub-pixel creep at almost-identity scale drew the text differently from the card at rest. The flight now reaches its final pose slightly early.
This commit is contained in:
1 parent
949e5e57ec
commit
48a30863c3
2 files changed
+28
-9
No files matched your search
@@ -19,8 +19,15 @@ body {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/*
|
||||
* Whole-pixel card size. pack-cards flies the card at its rounded layout size
|
||||
* scaled to the real one, then lays it out again when it lands; a fractional
|
||||
* size made the text re-layout and jump once the card had stopped.
|
||||
*/
|
||||
#stage .recap-deck {
|
||||
width: min(52vh, 78vw);
|
||||
aspect-ratio: auto;
|
||||
height: round(down, calc(min(52vh, 78vw) * 88 / 63), 1px);
|
||||
width: round(down, min(52vh, 78vw), 1px);
|
||||
}
|
||||
|
||||
#stage .recap-pack-scene {
|
||||
|
||||
@@ -55,13 +55,22 @@ const createFace = () => {
|
||||
* library: the rise out of the pack eases exponentially in and out,
|
||||
* everything after the card clears the pack is stretched so the flip has time
|
||||
* for three extra turns, and the flip eases out like a flicked card slowing to
|
||||
* a stop while sparkles burst around it.
|
||||
* a stop while sparkles burst around it. The spin lands flat a moment before
|
||||
* the card stops gliding: Chrome redraws text on a slightly tilted card
|
||||
* differently from a flat one, so ending both together made the text hop
|
||||
* after the card looked still.
|
||||
*/
|
||||
const flight = Object.freeze({duration: 1750, clearAt: 900});
|
||||
/**
|
||||
* The flight reaches its final pose `settleMs` (of the original 1750ms)
|
||||
* early, skipping a sub-pixel creep: the text drawn on the card's last scaled
|
||||
* frames differs from the text once the card is laid out at rest, so it
|
||||
* visibly hopped when the card landed.
|
||||
*/
|
||||
const flight = Object.freeze({duration: 1750, clearAt: 900, settleMs: 60});
|
||||
/** Exponential ease-in-out, as a CSS timing function. */
|
||||
const easeInOutExpo = 'cubic-bezier(.87, 0, .13, 1)';
|
||||
const afterClearStretch = 1.65;
|
||||
const flip = Object.freeze({startDegrees: 180 + 3 * 360, easing: 'cubic-bezier(.3, .4, .25, 1)'});
|
||||
const flip = Object.freeze({startDegrees: 180 + 3 * 360, easing: 'cubic-bezier(.3, .4, .25, 1)', flatAt: 0.8});
|
||||
|
||||
/**
|
||||
* Maps a time in the original flight to the stretched one.
|
||||
@@ -148,8 +157,10 @@ Element.prototype.animate = function (keyframes, options) {
|
||||
const [start] = keyframes;
|
||||
const eased =
|
||||
start && cleared > 1 ? [{...start, easing: easeInOutExpo}, ...keyframes.slice(cleared - 1)] : keyframes;
|
||||
const rest = eased.at(-1);
|
||||
const stretched = eased.map((frame) => ({
|
||||
...frame,
|
||||
...(rest && at(frame) >= flight.duration - flight.settleMs ? {transform: rest.transform} : {}),
|
||||
offset: stretch(at(frame)) / total,
|
||||
}));
|
||||
return animate.call(this, stretched, {...options, duration: total});
|
||||
@@ -167,11 +178,12 @@ Element.prototype.animate = function (keyframes, options) {
|
||||
if (this.parentElement) {
|
||||
burstSparkles(this.parentElement, flight.clearAt, duration);
|
||||
}
|
||||
return animate.call(this, [{transform: `rotateY(${flip.startDegrees}deg)`}, keyframes[1] ?? {}], {
|
||||
...options,
|
||||
duration,
|
||||
easing: flip.easing,
|
||||
});
|
||||
const flat = keyframes[1] ?? {};
|
||||
return animate.call(
|
||||
this,
|
||||
[{transform: `rotateY(${flip.startDegrees}deg)`, easing: flip.easing}, {...flat, offset: flip.flatAt}, flat],
|
||||
{...options, duration, easing: 'linear'},
|
||||
);
|
||||
}
|
||||
return animate.call(this, keyframes, options);
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user