Add pregnancy timeline motion: growing slider fill, size pop, week-button wave
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LSDgjk1Agjy9Z2UH2n8bc3
This commit is contained in:
2 files changed
+70
-1
No files matched your search
+2
-1
@@ -266,7 +266,7 @@ button{font-family:inherit;}
|
||||
text-transform:uppercase;letter-spacing:0.05em;margin-bottom:8px;font-weight:600;}
|
||||
input[type="range"].week-slider{
|
||||
width:100%;-webkit-appearance:none;appearance:none;height:8px;border-radius:999px;
|
||||
background:linear-gradient(to right, var(--pregnancy-soft) 0%, var(--pregnancy-soft) 100%);
|
||||
background:linear-gradient(to right, var(--pregnancy) 0, var(--pregnancy) calc(11px + (100% - 22px) * var(--f,0)), var(--pregnancy-soft) calc(11px + (100% - 22px) * var(--f,0)), var(--pregnancy-soft) 100%);
|
||||
outline:none;cursor:pointer;
|
||||
}
|
||||
input[type="range"].week-slider::-webkit-slider-thumb{
|
||||
@@ -1074,3 +1074,4 @@ footer.note{
|
||||
<script src="vendor/three.min.js"></script>
|
||||
<script src="ring3d.js"></script>
|
||||
<script src="animations.js"></script>
|
||||
<script src="timeline.js"></script>
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/* CycleWise AU - pregnancy timeline motion (Step 3).
|
||||
- The week slider's track fills with colour up to the current week.
|
||||
It grows the first time you scroll to it, then follows every week change.
|
||||
- The baby-size picture pops a little when the week changes.
|
||||
- The 40 week buttons wave in the first time they appear.
|
||||
Cosmetic only: without GSAP the slider simply shows its normal look. */
|
||||
(function(){
|
||||
"use strict";
|
||||
var slider = document.getElementById("week-slider");
|
||||
var badge = document.getElementById("wk-badge");
|
||||
if (!slider || !badge) return;
|
||||
|
||||
var hasGsap = !!window.gsap;
|
||||
var reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
||||
var animate = hasGsap && !reduce;
|
||||
|
||||
var fill = { f: 0 };
|
||||
var target = 0;
|
||||
var introDone = false;
|
||||
|
||||
function paint(){ slider.style.setProperty("--f", fill.f.toFixed(4)); }
|
||||
function currentWeek(){
|
||||
var n = parseInt((badge.textContent || "").replace(/\D/g, ""), 10);
|
||||
return isNaN(n) ? (parseInt(slider.value, 10) || 1) : Math.max(1, Math.min(40, n));
|
||||
}
|
||||
function goTo(f){
|
||||
target = f;
|
||||
if (!introDone) return; // wait until the slider is on screen
|
||||
if (!animate) { fill.f = f; paint(); return; }
|
||||
gsap.to(fill, { f: f, duration: 0.6, ease: "power2.out", overwrite: true, onUpdate: paint });
|
||||
}
|
||||
|
||||
// Follow every week change, whether from the slider, a week button or the calendar.
|
||||
var lastWeek = currentWeek();
|
||||
target = (lastWeek - 1) / 39;
|
||||
new MutationObserver(function(){
|
||||
var w = currentWeek();
|
||||
if (w === lastWeek) return;
|
||||
lastWeek = w;
|
||||
goTo((w - 1) / 39);
|
||||
var blob = document.querySelector("#wk-blob svg");
|
||||
if (animate && blob) {
|
||||
gsap.fromTo(blob, { scale: 0.8, transformOrigin: "50% 50%" },
|
||||
{ scale: 1, duration: 0.5, ease: "back.out(2)", clearProps: "transform" });
|
||||
}
|
||||
}).observe(badge, { childList: true, characterData: true, subtree: true });
|
||||
|
||||
// First time the slider is visible: grow the fill from empty up to this week.
|
||||
new IntersectionObserver(function(entries, obs){
|
||||
if (!entries[0].isIntersecting) return;
|
||||
obs.disconnect();
|
||||
introDone = true;
|
||||
if (!animate) { fill.f = target; paint(); return; }
|
||||
gsap.to(fill, { f: target, duration: 1.2, ease: "power2.out", onUpdate: paint });
|
||||
}).observe(slider);
|
||||
|
||||
// First time the week buttons are visible: wave them in.
|
||||
var strip = document.getElementById("week-filmstrip");
|
||||
if (strip && animate) {
|
||||
new IntersectionObserver(function(entries, obs){
|
||||
if (!entries[0].isIntersecting) return;
|
||||
obs.disconnect();
|
||||
gsap.from(strip.querySelectorAll(".film-item"), {
|
||||
opacity: 0, scale: 0.8, duration: 0.4, stagger: 0.02, ease: "power2.out", clearProps: "all"
|
||||
});
|
||||
}).observe(strip);
|
||||
}
|
||||
})();
|
||||
Reference in new issue
Block a user