Find easy to follow instructions
<link rel="stylesheet" href="https://unpkg.com/lenis@1.3.15/dist/lenis.css" />
<script src="https://unpkg.com/lenis@1.3.15/dist/lenis.min.js"></script>
<script>
const lenis = new Lenis({ duration: 1.4 });
lenis.on('scroll', ScrollTrigger.update);
gsap.ticker.add((time) => {
lenis.raf(time * 1000);
});
gsap.ticker.lagSmoothing(0);
</script><script>
gsap.registerPlugin(Draggable, InertiaPlugin);
const init = () => {
const marquee = document.querySelector('[wb-data="marquee"]');
if (!marquee) return;
const duration = parseInt(marquee.getAttribute('duration'), 20) || 5;
const marqueeContent = marquee.firstChild;
if (!marqueeContent) return;
// Clone for seamless loop
const marqueeContentClone = marqueeContent.cloneNode(true);
marquee.append(marqueeContentClone);
// Make sure marquee can be grabbed
marquee.style.cursor = 'grab';
let tween;
let distanceToTranslate;
const playMarquee = () => {
let progress = tween ? tween.progress() : 0;
tween && tween.progress(0).kill();
const width = parseInt(getComputedStyle(marqueeContent).getPropertyValue('width'), 10);
const gap = parseInt(getComputedStyle(marqueeContent).getPropertyValue('column-gap'), 10);
distanceToTranslate = -1 * (gap + width);
tween = gsap.fromTo(marquee.children, { x: 0 }, { x: distanceToTranslate, duration, ease: 'none', repeat: -1 });
tween.progress(progress);
};
playMarquee();
// ---- PAUSE ON HOVER ----
marquee.addEventListener('mouseenter', () => {
if (tween) gsap.to(tween, { timeScale: 0, duration: 0.3 });
});
marquee.addEventListener('mouseleave', () => {
if (tween) gsap.to(tween, { timeScale: 1, duration: 0.3 });
});
// ---- DRAGGABLE ----
const proxy = document.createElement('div');
let startProgress = 0;
Draggable.create(proxy, {
type: 'x',
trigger: marquee,
inertia: true,
onPressInit() {
gsap.killTweensOf(tween);
tween.timeScale(0);
marquee.style.cursor = 'grabbing';
startProgress = tween.progress();
gsap.set(proxy, { x: 0 });
gsap.to('.card-testimonials', { scale: 0.95, duration: 0.2 });
},
onDrag() {
const progressDelta = this.x / distanceToTranslate;
let newProgress = startProgress + progressDelta;
newProgress = ((newProgress % 1) + 1) % 1;
tween.progress(newProgress);
},
onThrowUpdate() {
const progressDelta = this.x / distanceToTranslate;
let newProgress = startProgress + progressDelta;
newProgress = ((newProgress % 1) + 1) % 1;
tween.progress(newProgress);
},
onRelease() {
marquee.style.cursor = 'grab';
gsap.to('.card-testimonials', { scale: 1, duration: 0.3 });
},
onThrowComplete() {
const isHovering = marquee.matches(':hover');
gsap.to(tween, { timeScale: isHovering ? 0 : 1, duration: 0.3 });
},
});
// ---- DEBOUNCED RESIZE ----
function debounce(func) {
var timer;
return function (event) {
if (timer) clearTimeout(timer);
timer = setTimeout(() => func(), 500, event);
};
}
window.addEventListener('resize', debounce(playMarquee));
};
document.addEventListener('DOMContentLoaded', init);
</script><script>
const hourEl = document.querySelector('.hour');
const minuteEl = document.querySelector('.minute');
const colonEl = document.querySelector('.colon');
if (hourEl && minuteEl && colonEl) {
function updateTime() {
const now = new Date();
const hours = now.getHours();
const minutes = now.getMinutes();
hourEl.textContent = String(hours).padStart(2, '0');
minuteEl.textContent = String(minutes).padStart(2, '0');
}
updateTime();
setInterval(updateTime, 1000 * 10);
if (typeof gsap !== 'undefined') {
gsap.to(colonEl, {
opacity: 0,
duration: 0.6,
ease: 'power1.inOut',
repeat: -1,
yoyo: true,
});
}
}
</script>