This commit is contained in:
NotSoToothless
2026-06-05 10:09:15 -07:00
committed by GitHub
parent 9173d4097e
commit e9e83d4343
+3 -53
View File
@@ -79,10 +79,6 @@
/* no filter, no CSS transition — GSAP owns stroke-dashoffset each frame */ /* no filter, no CSS transition — GSAP owns stroke-dashoffset each frame */
} }
.timeline-line .comet {
fill: #F5F5DC;
filter: drop-shadow(0 0 8px rgba(144, 238, 144, 0.7));
}
.timeline-line .end-marker { .timeline-line .end-marker {
fill: #1b1b1b; fill: #1b1b1b;
stroke: rgba(144, 238, 144, 0.35); stroke: rgba(144, 238, 144, 0.35);
@@ -276,7 +272,6 @@
<path class="track" id="timelineTrack" d=""></path> <path class="track" id="timelineTrack" d=""></path>
<path class="progress" id="timelineProgress" d=""></path> <path class="progress" id="timelineProgress" d=""></path>
<circle class="end-marker" id="timelineEndMarker" r="5" cx="0" cy="0"></circle> <circle class="end-marker" id="timelineEndMarker" r="5" cx="0" cy="0"></circle>
<circle class="comet" id="timelineComet" r="6" cx="0" cy="0" style="opacity:0"></circle>
</svg> </svg>
<div class="timeline-grid"> <div class="timeline-grid">
@@ -598,7 +593,6 @@
<script src="/js/main.js?v=3"></script> <script src="/js/main.js?v=3"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/ScrollTrigger.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/ScrollTrigger.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lenis@1.1.14/dist/lenis.min.js"></script>
<!-- Serpentine timeline renderer --> <!-- Serpentine timeline renderer -->
<script> <script>
@@ -607,7 +601,6 @@
var svg = document.getElementById('timelineLine'); var svg = document.getElementById('timelineLine');
var track = document.getElementById('timelineTrack'); var track = document.getElementById('timelineTrack');
var progress = document.getElementById('timelineProgress'); var progress = document.getElementById('timelineProgress');
var comet = document.getElementById('timelineComet');
if (!timeline || !svg) return; if (!timeline || !svg) return;
var nodes = Array.prototype.slice.call(timeline.querySelectorAll('.timeline-node')); var nodes = Array.prototype.slice.call(timeline.querySelectorAll('.timeline-node'));
@@ -688,37 +681,9 @@
endMarker.setAttribute('cx', ep.x.toFixed(1)); endMarker.setAttribute('cx', ep.x.toFixed(1));
endMarker.setAttribute('cy', ep.y.toFixed(1)); endMarker.setAttribute('cy', ep.y.toFixed(1));
} }
updateComet(pathLength);
return { pts: pts, len: pathLength }; return { pts: pts, len: pathLength };
} }
function updateComet(len) {
if (reduceMotion || drawProgress <= 0 || drawProgress >= 1 || !_samples || !_samples.length) {
comet.style.opacity = 0;
return;
}
// Binary search then interpolate — smooth position without getPointAtLength()
var target = len * drawProgress;
var lo = 0, hi = _samples.length - 1;
while (lo < hi) {
var mid = (lo + hi) >> 1;
if (_samples[mid].l < target) lo = mid + 1; else hi = mid;
}
var cx, cy;
if (lo > 0) {
var a = _samples[lo - 1], b = _samples[lo];
var t = (b.l > a.l) ? (target - a.l) / (b.l - a.l) : 0;
cx = (a.x + (b.x - a.x) * t).toFixed(1);
cy = (a.y + (b.y - a.y) * t).toFixed(1);
} else {
cx = _samples[0].x.toFixed(1);
cy = _samples[0].y.toFixed(1);
}
comet.setAttribute('cx', cx);
comet.setAttribute('cy', cy);
comet.style.opacity = 1;
}
// Find roughly how far along the path a point sits (coarse sampling). // Find roughly how far along the path a point sits (coarse sampling).
var _samples = null; var _samples = null;
function lengthAtPoint(target, len) { function lengthAtPoint(target, len) {
@@ -785,10 +750,8 @@
function renderProgress() { function renderProgress() {
drawProgress = state.progress; drawProgress = state.progress;
progress.style.strokeDashoffset = pathLength * (1 - drawProgress); progress.style.strokeDashoffset = pathLength * (1 - drawProgress);
updateComet(pathLength);
revealReachedNodes(); revealReachedNodes();
if (drawProgress >= 1) { if (drawProgress >= 1) {
comet.style.opacity = 0;
nodes.forEach(function (n, index) { nodes.forEach(function (n, index) {
nodeRevealed[index] = true; nodeRevealed[index] = true;
n.classList.add('is-visible'); n.classList.add('is-visible');
@@ -859,7 +822,7 @@
start: 'top 70%', start: 'top 70%',
endTrigger: nodes[nodes.length - 1] || timeline, endTrigger: nodes[nodes.length - 1] || timeline,
end: 'top 60%', end: 'top 60%',
scrub: 0.6, scrub: true,
invalidateOnRefresh: true, invalidateOnRefresh: true,
onUpdate: function (self) { onUpdate: function (self) {
var p = Math.min(1, preRevealProgress + self.progress * (1 - preRevealProgress)); var p = Math.min(1, preRevealProgress + self.progress * (1 - preRevealProgress));
@@ -893,21 +856,8 @@
hint = null; hint = null;
} }
if (window.Lenis) { if (window.scrollY > 8) hideScrollHint();
var lenis = new Lenis({ window.addEventListener('scroll', hideScrollHint, { once: true, passive: true });
duration: 0.9,
easing: function (t) { return 1 - Math.pow(1 - t, 3); },
smoothWheel: true
});
lenis.on('scroll', function () {
hideScrollHint();
ScrollTrigger.update();
});
gsap.ticker.add(function (time) { lenis.raf(time * 1000); });
gsap.ticker.lagSmoothing(0);
} else {
window.addEventListener('scroll', hideScrollHint, { once: true });
}
} else { } else {
advanceTo(1, 0); advanceTo(1, 0);
} }