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;
|
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 {
|
#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 {
|
#stage .recap-pack-scene {
|
||||||
|
|||||||
@@ -55,13 +55,22 @@ const createFace = () => {
|
|||||||
* library: the rise out of the pack eases exponentially in and out,
|
* 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
|
* 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
|
* 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. */
|
/** Exponential ease-in-out, as a CSS timing function. */
|
||||||
const easeInOutExpo = 'cubic-bezier(.87, 0, .13, 1)';
|
const easeInOutExpo = 'cubic-bezier(.87, 0, .13, 1)';
|
||||||
const afterClearStretch = 1.65;
|
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.
|
* 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 [start] = keyframes;
|
||||||
const eased =
|
const eased =
|
||||||
start && cleared > 1 ? [{...start, easing: easeInOutExpo}, ...keyframes.slice(cleared - 1)] : keyframes;
|
start && cleared > 1 ? [{...start, easing: easeInOutExpo}, ...keyframes.slice(cleared - 1)] : keyframes;
|
||||||
|
const rest = eased.at(-1);
|
||||||
const stretched = eased.map((frame) => ({
|
const stretched = eased.map((frame) => ({
|
||||||
...frame,
|
...frame,
|
||||||
|
...(rest && at(frame) >= flight.duration - flight.settleMs ? {transform: rest.transform} : {}),
|
||||||
offset: stretch(at(frame)) / total,
|
offset: stretch(at(frame)) / total,
|
||||||
}));
|
}));
|
||||||
return animate.call(this, stretched, {...options, duration: total});
|
return animate.call(this, stretched, {...options, duration: total});
|
||||||
@@ -167,11 +178,12 @@ Element.prototype.animate = function (keyframes, options) {
|
|||||||
if (this.parentElement) {
|
if (this.parentElement) {
|
||||||
burstSparkles(this.parentElement, flight.clearAt, duration);
|
burstSparkles(this.parentElement, flight.clearAt, duration);
|
||||||
}
|
}
|
||||||
return animate.call(this, [{transform: `rotateY(${flip.startDegrees}deg)`}, keyframes[1] ?? {}], {
|
const flat = keyframes[1] ?? {};
|
||||||
...options,
|
return animate.call(
|
||||||
duration,
|
this,
|
||||||
easing: flip.easing,
|
[{transform: `rotateY(${flip.startDegrees}deg)`, easing: flip.easing}, {...flat, offset: flip.flatAt}, flat],
|
||||||
});
|
{...options, duration, easing: 'linear'},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return animate.call(this, keyframes, options);
|
return animate.call(this, keyframes, options);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in new issue
Block a user