timeline (#1301)
This commit is contained in:
+3
-53
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user