intro updates
This commit is contained in:
15
src/App.vue
15
src/App.vue
@@ -1880,9 +1880,10 @@ async function playIntro() {
|
||||
// duration + base delay. JS rebuilds spans per play (so language
|
||||
// switches still split correctly) and measures entry from live word
|
||||
// count. Each word carries the introWord blur resolve.
|
||||
const STAGGER = 0.22
|
||||
const PER_WORD = 1.05
|
||||
const BASE = 0.05
|
||||
const SPEED = 1.25
|
||||
const STAGGER = 0.22 * SPEED
|
||||
const PER_WORD = 1.05 * SPEED
|
||||
const BASE = 0.05 * SPEED
|
||||
const stages = []
|
||||
for (let n = 1; n <= 3; n++) {
|
||||
const stageEl = overlay.querySelector('.stage-' + n)
|
||||
@@ -1926,10 +1927,10 @@ async function playIntro() {
|
||||
const entryMs = Math.round((BASE + (Math.max(0, words.length - 1)) * STAGGER + PER_WORD) * 1000)
|
||||
// Bigger hold on stage 1 so the opening line lingers; stage 3 (the
|
||||
// longest sentence) holds the longest.
|
||||
const hold = n === 3 ? 1500 : (n === 1 ? 1200 : 900)
|
||||
const hold = n === 3 ? 1875 : (n === 1 ? 1500 : 1125)
|
||||
stages.push({ sel: '.stage-' + n, enter: entryMs, hold })
|
||||
}
|
||||
const exit = 800 // matches the introOut (smoke out) duration
|
||||
const exit = 1000 // default matches the slowed introOut smoke-out duration
|
||||
for (let i = 0; i < stages.length; i++) {
|
||||
const s = stages[i]
|
||||
const el = overlay.querySelector(s.sel)
|
||||
@@ -1945,7 +1946,7 @@ async function playIntro() {
|
||||
// instantly and the smoke-out on the parent would dissolve into
|
||||
// an already-empty wrapper.
|
||||
el.classList.add('leaving')
|
||||
await sleep(exit)
|
||||
await sleep(i === 0 ? 1500 : exit)
|
||||
el.classList.remove('leaving')
|
||||
el.classList.remove('active')
|
||||
}
|
||||
@@ -1955,7 +1956,7 @@ async function playIntro() {
|
||||
// overlay fade-out as one motion.
|
||||
overlay.classList.add('done')
|
||||
document.body.classList.add('intro-done')
|
||||
await sleep(900)
|
||||
await sleep(1125)
|
||||
overlay.classList.add('gone')
|
||||
}
|
||||
function maybePlayIntro({ skip = false } = {}) {
|
||||
|
||||
@@ -1191,7 +1191,7 @@ input[type=range]::-moz-range-thumb {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
pointer-events: none;
|
||||
transition: opacity 1.1s cubic-bezier(0.22, 0.61, 0.36, 1);
|
||||
transition: opacity 1.375s cubic-bezier(0.22, 0.61, 0.36, 1);
|
||||
}
|
||||
.intro-overlay.done { opacity: 0; }
|
||||
.intro-overlay.gone { display: none; }
|
||||
@@ -1262,13 +1262,22 @@ input[type=range]::-moz-range-thumb {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
transition:
|
||||
opacity 0.25s ease 0.05s,
|
||||
transform 0.55s cubic-bezier(0.18, 0.89, 0.32, 1.18) 0.05s;
|
||||
opacity 0.45s ease 0.06s,
|
||||
transform 0.75s cubic-bezier(0.18, 0.89, 0.32, 1.18) 0.06s;
|
||||
}
|
||||
.intro-stage.stage-1.active .stage-icon {
|
||||
animation: introIconIn 1.05s 0.18s cubic-bezier(0.18, 0.89, 0.32, 1.18) both;
|
||||
transition: none;
|
||||
}
|
||||
@keyframes introIconIn {
|
||||
0% { opacity: 0; transform: translateY(10px) scale(0.72); }
|
||||
70% { opacity: 1; transform: translateY(0) scale(1.04); }
|
||||
100% { opacity: 1; transform: translateY(0) scale(1); }
|
||||
}
|
||||
.intro-stage.active .stage-icon .glyph path,
|
||||
.intro-stage.active .stage-icon .glyph line,
|
||||
.intro-stage.active .stage-icon .glyph circle {
|
||||
animation: introDraw 0.9s 0.1s cubic-bezier(0.22, 0.61, 0.36, 1) forwards;
|
||||
animation: introDraw 1.125s 0.125s cubic-bezier(0.22, 0.61, 0.36, 1) forwards;
|
||||
}
|
||||
@keyframes introDraw {
|
||||
to { stroke-dashoffset: 0; }
|
||||
@@ -1282,7 +1291,7 @@ input[type=range]::-moz-range-thumb {
|
||||
transform-origin: center;
|
||||
}
|
||||
.intro-stage.active .stage-icon .filled-icon path {
|
||||
animation: introGlyphPop 0.65s 0.18s cubic-bezier(0.18, 0.89, 0.32, 1.18) forwards;
|
||||
animation: introGlyphPop 0.9s 0.225s cubic-bezier(0.18, 0.89, 0.32, 1.18) forwards;
|
||||
}
|
||||
@keyframes introGlyphPop {
|
||||
to { opacity: 1; transform: scale(1); }
|
||||
@@ -1314,11 +1323,11 @@ input[type=range]::-moz-range-thumb {
|
||||
/* Stage 1 — the shield border appears first; the filled check ticks in
|
||||
near the end of the sentence, after "prepare" has landed. */
|
||||
.intro-stage.stage-1.active .i-shield-outline {
|
||||
animation: introDraw 0.78s 0.45s cubic-bezier(0.22, 0.61, 0.36, 1) forwards;
|
||||
animation: introDraw 1.05s 0.56s cubic-bezier(0.22, 0.61, 0.36, 1) forwards;
|
||||
opacity: 1;
|
||||
}
|
||||
.intro-stage.stage-1.active .i-secure-tick {
|
||||
animation: tickFillIn 0.48s 2.6s cubic-bezier(0.18, 0.89, 0.32, 1.18) forwards;
|
||||
animation: tickFillIn 0.72s 3.25s cubic-bezier(0.18, 0.89, 0.32, 1.18) forwards;
|
||||
transform-box: fill-box;
|
||||
transform-origin: center;
|
||||
}
|
||||
@@ -1358,7 +1367,7 @@ input[type=range]::-moz-range-thumb {
|
||||
}
|
||||
.intro-stage.stage-3.active .icon-clock .i-hand {
|
||||
animation: introDraw 0.35s 0.70s cubic-bezier(0.22, 0.61, 0.36, 1) forwards,
|
||||
clockSweep 2.2s 1.35s linear forwards;
|
||||
clockSweep 2.75s 2.35s linear forwards;
|
||||
}
|
||||
@keyframes clockSweep {
|
||||
from { transform: rotate(0deg); }
|
||||
@@ -1433,10 +1442,10 @@ input[type=range]::-moz-range-thumb {
|
||||
.intro-stage .intro-text .mobile-break { display: none; }
|
||||
}
|
||||
.intro-stage.active .intro-text > .word {
|
||||
animation: introWord 1.05s cubic-bezier(0.22, 0.61, 0.36, 1) forwards;
|
||||
animation: introWord 1.3125s cubic-bezier(0.22, 0.61, 0.36, 1) forwards;
|
||||
}
|
||||
.intro-stage.stage-1.active .intro-text > .word {
|
||||
animation-delay: calc(var(--word-delay, 0s) + 0.9s) !important;
|
||||
animation-delay: calc(var(--word-delay, 0s) + 1.125s) !important;
|
||||
}
|
||||
@keyframes introWord {
|
||||
0% { opacity: 0; transform: translateY(14px); }
|
||||
@@ -1447,7 +1456,10 @@ input[type=range]::-moz-range-thumb {
|
||||
Same effect for every stage so each sentence dissolves into haze
|
||||
before the next one resolves. */
|
||||
.intro-stage.leaving .intro-text {
|
||||
animation: introOut 0.8s cubic-bezier(0.4, 0, 1, 1) forwards;
|
||||
animation: introOut 1s cubic-bezier(0.4, 0, 1, 1) forwards;
|
||||
}
|
||||
.intro-stage.stage-1.leaving .intro-text {
|
||||
animation-duration: 1.5s;
|
||||
}
|
||||
@keyframes introOut {
|
||||
0% { opacity: 1; filter: blur(0); transform: translateY(0); }
|
||||
|
||||
Reference in New Issue
Block a user