UNPKG

cursor-blob

Version:

Lightweight library for animated, interactive cursors using GSAP

2 lines (1 loc) 2.22 kB
(function(r,a){typeof exports=="object"&&typeof module<"u"?module.exports=a(require("gsap")):typeof define=="function"&&define.amd?define(["gsap"],a):(r=typeof globalThis<"u"?globalThis:r||self,r.CursorBlob=a(r.gsap))})(this,(function(r){"use strict";const u=Math.PI,m=.95,c=2;class i{static gsap=r;cursor;cursorRim;cursorDot;duration;ease;pos={x:0,y:0};vel={x:0,y:0};animFrame=null;boundMove=this.setFromEvent.bind(this);rimX;rimY;rimRotate;rimScaleX;rimScaleY;dotX;dotY;static registerGSAP(t){i.gsap=t}static getScale(t,s){const e=Math.hypot(t,s);return Math.min(e/485,.35)}static getAngle(t,s){return Math.atan2(s,t)*180/u}constructor({cursorEl:t,cursorRimEl:s,cursorDotEl:e,duration:o=m,ease:n="expo.out"}){this.cursor=t,this.cursorRim=s,this.cursorDot=e,this.duration=o,this.ease=n,this.setupQuickSetters(),window.addEventListener("pointermove",this.boundMove),this.animate()}setupQuickSetters(){const t=i.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:o}=this.vel,n=i.getAngle(e,o),h=i.getScale(e,o);this.rimX(t),this.rimY(s),this.rimRotate(n),this.rimScaleX(1+h),this.rimScaleY(1-h),this.dotX(t+e*.1),this.dotY(s+o*.1)}animate=()=>{this.loop(),this.animFrame=requestAnimationFrame(this.animate)};setFromEvent(t){const{clientX:s,clientY:e}=t,o=this.cursorRim.offsetWidth/c,n=this.cursorRim.offsetHeight/c;i.gsap.killTweensOf(this.pos),i.gsap.to(this.pos,{x:s-o,y:e-n,duration:this.duration,ease:this.ease,onUpdate:()=>{this.vel.x=s-o-this.pos.x,this.vel.y=e-n-this.pos.y,this.applyStyle(t)}})}applyStyle(t){let s=t.target;for(;s&&!s.dataset?.cursorStyle&&s!==document.body;)s=s.parentElement;const e=s?.dataset?.cursorStyle??"default";this.cursor.className=`cursor cursor--${e}`}destroy(){window.removeEventListener("pointermove",this.boundMove),i.gsap.killTweensOf(this.pos),this.animFrame!==null&&cancelAnimationFrame(this.animFrame)}}return i}));