instructions
Instructions
Webflow Template User Guide
Webflow Template User Guide
window._cursorPause() and window._cursorResume() so other scripts can hide it on demand.<script>
window.Webflow = window.Webflow || [];
window.Webflow.push(function () {
// ==================================================
// MAIN CURSOR
// ==================================================
if (window._cursorCoreInit) return;
window._cursorCoreInit = true;
var cursor = document.querySelector(".cursor-core");
var pointer = document.querySelector(".cursor-pointer");
if (!cursor) return;
var mouseX = -100;
var mouseY = -100;
var x = -100;
var y = -100;
var paused = false;
// initial
gsap.set(cursor, {
xPercent: -50,
yPercent: -50,
x: x,
y: y
});
// smooth follow
gsap.ticker.add(function () {
x += (mouseX - x) * 0.15;
y += (mouseY - y) * 0.15;
gsap.set(cursor, {
x: x,
y: y
});
});
// track mouse
window.addEventListener("mousemove", function (e) {
mouseX = e.clientX;
mouseY = e.clientY;
});
// =========================================
// HIDE POINTER ONLY
// =========================================
window._cursorPause = function () {
paused = true;
if (!pointer) return;
gsap.to(pointer, {
opacity: 0,
duration: 0.2,
overwrite: true
});
};
// =========================================
// SHOW POINTER AGAIN
// =========================================
window._cursorResume = function () {
paused = false;
if (!pointer) return;
gsap.to(pointer, {
opacity: 1,
duration: 0.2,
overwrite: true
});
};
});
</script>.cta-content-wrapper — the parent container that contains all blur elementsbg-blur — the individual blur blobs that will be animated<script>
document.addEventListener("DOMContentLoaded", () => {
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
const blurs = document.querySelectorAll(".cta-content-wrapper .bg-blur");
if (!blurs.length) return;
// Konfigurasi gerak berbeda per blob (amplitudo dalam %, durasi dalam detik)
const configs = [
{ ax: 40, ay: 30, dx: 6, dy: 4, rot: 1 }, // blob 1
{ ax: 35, ay: 45, dx: 5, dy: 7, rot: -1 }, // blob 2
{ ax: 50, ay: 25, dx: 7, dy: 5, rot: 1 }, // blob 3
];
blurs.forEach((el, i) => {
const c = configs[i % configs.length];
// Gerak horizontal — melengkung karena ease sinus
gsap.to(el, {
xPercent: c.ax,
duration: c.dx,
ease: "sine.inOut",
repeat: -1,
yoyo: true,
});
// Gerak vertikal — durasi beda → lintasan jadi kurva, bukan garis lurus
gsap.to(el, {
yPercent: c.ay * c.rot,
duration: c.dy,
ease: "sine.inOut",
repeat: -1,
yoyo: true,
});
// Sedikit "napas" skala biar terasa hidup (opsional)
gsap.to(el, {
scale: 1.15,
duration: c.dx + 2,
ease: "sine.inOut",
repeat: -1,
yoyo: true,
});
});
});
</script>0 to its final value only once, providing an engaging way to highlight statistics and key metrics.counter-number-wrapper — the parent container used as the ScrollTrigger targetcounter-number-up — the container that holds the number to animate<script>
window.Webflow = window.Webflow || [];
window.Webflow.push(function () {
gsap.registerPlugin(ScrollTrigger);
document.querySelectorAll(".counter-number-wrapper").forEach((counter)=>{
const number = counter.querySelector(".counter-number-up > *");
if (!number) return;
const finalValue = parseInt(number.textContent);
let obj = { value: 0 };
gsap.to(obj,{
value: finalValue,
duration: 2,
ease: "expo.out",
scrollTrigger:{
trigger: counter,
start: "top 85%",
once: true
},
onUpdate(){
number.textContent = Math.round(obj.value);
}
});
});
});
</script>