cursor-blob
Version:
Lightweight library for animated, interactive cursors using GSAP
68 lines (67 loc) • 2.98 kB
JavaScript
var u = Object.defineProperty;
var m = (c, t, s) => t in c ? u(c, t, { enumerable: !0, configurable: !0, writable: !0, value: s }) : c[t] = s;
var i = (c, t, s) => m(c, typeof t != "symbol" ? t + "" : t, s);
import l from "gsap";
const p = Math.PI, o = class o {
constructor({ cursorEl: t, cursorRimEl: s, cursorDotEl: e, duration: r = 0.95, ease: a = "expo.out" }) {
i(this, "cursor");
i(this, "cursorRim");
i(this, "cursorDot");
i(this, "duration");
i(this, "ease");
i(this, "pos", { x: 0, y: 0 });
i(this, "vel", { x: 0, y: 0 });
i(this, "animFrame", null);
i(this, "boundMove", this.setFromEvent.bind(this));
i(this, "rimX");
i(this, "rimY");
i(this, "rimRotate");
i(this, "rimScaleX");
i(this, "rimScaleY");
i(this, "dotX");
i(this, "dotY");
i(this, "animate", () => {
this.loop(), this.animFrame = requestAnimationFrame(this.animate);
});
this.cursor = t, this.cursorRim = s, this.cursorDot = e, this.duration = r, this.ease = a, this.setupQuickSetters(), window.addEventListener("pointermove", this.boundMove), this.animate();
}
static registerGSAP(t) {
o.gsap = t;
}
static getScale(t, s) {
const e = Math.hypot(t, s);
return Math.min(e / 485, 0.35);
}
static getAngle(t, s) {
return 180 * Math.atan2(s, t) / p;
}
setupQuickSetters() {
const t = o.gsap;
this.rimX = t.quickSetter(this.cursorRim, "x", "px"), this.rimY = t.quickSetter(this.cursorRim, "y", "px"), this.rimRotate = t.quickSetter(this.cursorRim, "rotate", "deg"), this.rimScaleX = t.quickSetter(this.cursorRim, "scaleX"), this.rimScaleY = t.quickSetter(this.cursorRim, "scaleY"), this.dotX = t.quickSetter(this.cursorDot, "x", "px"), this.dotY = t.quickSetter(this.cursorDot, "y", "px");
}
loop() {
const { x: t, y: s } = this.pos, { x: e, y: r } = this.vel, a = o.getAngle(e, r), h = o.getScale(e, r);
this.rimX(t), this.rimY(s), this.rimRotate(a), this.rimScaleX(1 + h), this.rimScaleY(1 - h), this.dotX(t + 0.1 * e), this.dotY(s + 0.1 * r);
}
setFromEvent(t) {
const { clientX: s, clientY: e } = t, r = this.cursorRim.offsetWidth / 2, a = this.cursorRim.offsetHeight / 2;
o.gsap.killTweensOf(this.pos), o.gsap.to(this.pos, { x: s - r, y: e - a, duration: this.duration, ease: this.ease, onUpdate: () => {
this.vel.x = s - r - this.pos.x, this.vel.y = e - a - this.pos.y, this.applyStyle(t);
} });
}
applyStyle(t) {
var r, a;
let s = t.target;
for (; s && !((r = s.dataset) != null && r.cursorStyle) && s !== document.body; ) s = s.parentElement;
const e = ((a = s == null ? void 0 : s.dataset) == null ? void 0 : a.cursorStyle) ?? "default";
this.cursor.className = `cursor cursor--${e}`;
}
destroy() {
window.removeEventListener("pointermove", this.boundMove), o.gsap.killTweensOf(this.pos), this.animFrame !== null && cancelAnimationFrame(this.animFrame);
}
};
i(o, "gsap", l);
let n = o;
export {
n as default
};