UNPKG

react-creative-cursor

Version:

A creative and customizable React cursor component.

442 lines (413 loc) 16.7 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var React = require('react'); var React__default = _interopDefault(React); var gsap = require('gsap'); function getScale(diffX, diffY) { if (diffX && diffY) { var distance = Math.sqrt(Math.pow(diffX, 2) + Math.pow(diffY, 2)); return Math.min(distance / 735, 0.35); } return; } function getAngle(diffX, diffY) { if (diffX && diffY) { return Math.atan2(diffY, diffX) * 180 / Math.PI; } return; } var EMPTY = {}; function useInstance(value) { if (value === void 0) { value = {}; } var ref = React.useRef(EMPTY); if (ref.current === EMPTY) { ref.current = typeof value === 'function' ? value() : value; } return ref.current; } function useTicker(callback, paused) { React.useLayoutEffect(function () { if (!paused && callback) { gsap.gsap.ticker.add(callback); } return function () { gsap.gsap.ticker.remove(callback); }; }, [callback, paused]); } var Cursor = function Cursor(_ref) { var _ref$isGelly = _ref.isGelly, isGelly = _ref$isGelly === void 0 ? false : _ref$isGelly, _ref$animationDuratio = _ref.animationDuration, animationDuration = _ref$animationDuratio === void 0 ? 1.25 : _ref$animationDuratio, _ref$animationEase = _ref.animationEase, animationEase = _ref$animationEase === void 0 ? gsap.Expo.easeOut : _ref$animationEase, _ref$gellyAnimationAm = _ref.gellyAnimationAmount, gellyAnimationAmount = _ref$gellyAnimationAm === void 0 ? 50 : _ref$gellyAnimationAm, _ref$stickAnimationAm = _ref.stickAnimationAmount, stickAnimationAmount = _ref$stickAnimationAm === void 0 ? 0.09 : _ref$stickAnimationAm, _ref$stickAnimationDu = _ref.stickAnimationDuration, stickAnimationDuration = _ref$stickAnimationDu === void 0 ? 0.7 : _ref$stickAnimationDu, _ref$stickAnimationEa = _ref.stickAnimationEase, stickAnimationEase = _ref$stickAnimationEa === void 0 ? gsap.Power4.easeOut : _ref$stickAnimationEa, _ref$magneticAnimatio = _ref.magneticAnimationAmount, magneticAnimationAmount = _ref$magneticAnimatio === void 0 ? 0.2 : _ref$magneticAnimatio, _ref$magneticAnimatio2 = _ref.magneticAnimationDuration, magneticAnimationDuration = _ref$magneticAnimatio2 === void 0 ? 0.7 : _ref$magneticAnimatio2, _ref$magneticAnimatio3 = _ref.magneticAnimationEase, magneticAnimationEase = _ref$magneticAnimatio3 === void 0 ? gsap.Power4.easeOut : _ref$magneticAnimatio3, _ref$colorAnimationEa = _ref.colorAnimationEase, colorAnimationEase = _ref$colorAnimationEa === void 0 ? gsap.Power4.easeOut : _ref$colorAnimationEa, _ref$colorAnimationDu = _ref.colorAnimationDuration, colorAnimationDuration = _ref$colorAnimationDu === void 0 ? 0.2 : _ref$colorAnimationDu, _ref$backgroundImageA = _ref.backgroundImageAnimationEase, backgroundImageAnimationEase = _ref$backgroundImageA === void 0 ? undefined : _ref$backgroundImageA, _ref$backgroundImageA2 = _ref.backgroundImageAnimationDuration, backgroundImageAnimationDuration = _ref$backgroundImageA2 === void 0 ? 0 : _ref$backgroundImageA2, _ref$sizeAnimationEas = _ref.sizeAnimationEase, sizeAnimationEase = _ref$sizeAnimationEas === void 0 ? gsap.Expo.easeOut : _ref$sizeAnimationEas, _ref$sizeAnimationDur = _ref.sizeAnimationDuration, sizeAnimationDuration = _ref$sizeAnimationDur === void 0 ? 0.5 : _ref$sizeAnimationDur, _ref$textAnimationEas = _ref.textAnimationEase, textAnimationEase = _ref$textAnimationEas === void 0 ? gsap.Expo.easeOut : _ref$textAnimationEas, _ref$textAnimationDur = _ref.textAnimationDuration, textAnimationDuration = _ref$textAnimationDur === void 0 ? 1 : _ref$textAnimationDur, _ref$cursorSize = _ref.cursorSize, cursorSize = _ref$cursorSize === void 0 ? 48 : _ref$cursorSize, _ref$cursorBackgrounC = _ref.cursorBackgrounColor, cursorBackgrounColor = _ref$cursorBackgrounC === void 0 ? '#000' : _ref$cursorBackgrounC, _ref$exclusionBackgro = _ref.exclusionBackgroundColor, exclusionBackgroundColor = _ref$exclusionBackgro === void 0 ? '#fff' : _ref$exclusionBackgro, _ref$cursorInnerColor = _ref.cursorInnerColor, cursorInnerColor = _ref$cursorInnerColor === void 0 ? '#fff' : _ref$cursorInnerColor; var cursor = React.useRef(null); var cursorInner = React.useRef(null); var pos = useInstance(function () { return { x: 0, y: 0 }; }); var vel = useInstance(function () { return { x: 0, y: 0 }; }); var set = useInstance(); React.useLayoutEffect(function () { set.x = gsap.gsap.quickSetter(cursor.current, 'x', 'px'); set.y = gsap.gsap.quickSetter(cursor.current, 'y', 'px'); if (isGelly) { set.r = gsap.gsap.quickSetter(cursor.current, 'rotate', 'deg'); set.sx = gsap.gsap.quickSetter(cursor.current, 'scaleX'); set.sy = gsap.gsap.quickSetter(cursor.current, 'scaleY'); set.width = gsap.gsap.quickSetter(cursor.current, 'width', 'px'); set.rt = gsap.gsap.quickSetter(cursorInner.current, 'rotate', 'deg'); } }); var loop = React.useCallback(function () { var rotation = getAngle(vel.x, vel.y); var scale = getScale(vel.x, vel.y); set.x(pos.x); set.y(pos.y); if (isGelly && scale && rotation && cursor.current) { var _cursor$current; set.width(((_cursor$current = cursor.current) == null ? void 0 : _cursor$current.style.height) + scale * gellyAnimationAmount); set.r(rotation); set.sx(1 + scale); set.sy(1 - scale); set.rt(-rotation); } }, [gellyAnimationAmount, isGelly, pos.x, pos.y, set, vel.x, vel.y]); React.useLayoutEffect(function () { var sizeElements = document.querySelectorAll('[data-cursor-size]'); var textElements = document.querySelectorAll('[data-cursor-text]'); var colorElements = document.querySelectorAll('[data-cursor-color]'); var backgroundImageElements = document.querySelectorAll('[data-cursor-background-image]'); var magneticElements = document.querySelectorAll('[data-cursor-magnetic]'); var stickElements = document.querySelectorAll('[data-cursor-stick]'); var exclusionElements = document.querySelectorAll('[data-cursor-exclusion]'); var stickStatus = false; var hasExclusionAlready = false; var setFromEvent = function setFromEvent(e) { var areatarget = e.target; var target; var bound; var x = e.clientX; var y = e.clientY; var duration = animationDuration; var ease = animationEase; if (stickStatus) { var _target; target = areatarget.querySelector(areatarget.dataset['cursorStick']); bound = (_target = target) == null ? void 0 : _target.getBoundingClientRect(); if (target && bound) { y = bound.top + target.clientHeight / 2 - (bound.top + target.clientHeight / 2 - e.clientY) * stickAnimationAmount; x = bound.left + target.clientWidth / 2 - (bound.left + target.clientWidth / 2 - e.clientX) * stickAnimationAmount; duration = stickAnimationDuration; ease = stickAnimationEase; } } gsap.gsap.set(pos, {}); var xTo = gsap.gsap.quickTo(pos, 'x', { duration: duration, ease: ease, onUpdate: function onUpdate() { if (pos.x) vel.x = x - pos.x; } }); var yTo = gsap.gsap.quickTo(pos, 'y', { duration: duration, ease: ease, onUpdate: function onUpdate() { if (pos.y) vel.y = y - pos.y; } }); xTo(x); yTo(y); loop(); }; window.addEventListener('mousemove', function (e) { setFromEvent(e); }); document.body.addEventListener('mouseenter', function (e) { if (e.target instanceof HTMLElement && cursor.current) { gsap.gsap.to("#" + cursor.current.id, { opacity: 1, duration: animationDuration, ease: animationEase }); } }); document.body.addEventListener('mouseleave', function (e) { if (e.target instanceof HTMLElement && cursor.current) { gsap.gsap.to("#" + cursor.current.id, { opacity: 0, duration: animationDuration, ease: animationEase }); } }); sizeElements.forEach(function (el) { el.addEventListener('mouseenter', function (e) { if (e.target instanceof HTMLElement && cursor.current) { gsap.gsap.to("#" + cursor.current.id, { width: "" + e.target.dataset['cursorSize'], height: "" + e.target.dataset['cursorSize'], duration: sizeAnimationDuration, ease: sizeAnimationEase }); } }); }); sizeElements.forEach(function (el) { el.addEventListener('mouseleave', function (e) { if (e.target instanceof HTMLElement && cursor.current) { gsap.gsap.to("#" + cursor.current.id, { width: "" + cursorSize, height: "" + cursorSize, duration: sizeAnimationDuration, ease: sizeAnimationEase }); } }); }); textElements.forEach(function (el) { el.addEventListener('mouseenter', function (e) { if (e.target instanceof HTMLElement && cursorInner.current) { cursorInner.current.textContent = "" + e.target.dataset['cursorText']; gsap.gsap.to("#" + cursorInner.current.id, { scale: 1, opacity: 1, duration: textAnimationDuration, ease: textAnimationEase }); } }); }); textElements.forEach(function (el) { el.addEventListener('mouseleave', function (e) { if (e.target instanceof HTMLElement && cursorInner.current) { cursorInner.current.textContent = ''; gsap.gsap.to("#" + cursorInner.current.id, { scale: 0, opacity: 0, duration: textAnimationDuration, ease: textAnimationEase }); } }); }); colorElements.forEach(function (el) { el.addEventListener('mouseenter', function (e) { if (e.target instanceof HTMLElement && cursor.current) { gsap.gsap.to("#" + cursor.current.id, { backgroundColor: "" + e.target.dataset['cursorColor'], duration: colorAnimationDuration, ease: colorAnimationEase }); } }); }); colorElements.forEach(function (el) { el.addEventListener('mouseleave', function (e) { if (e.target instanceof HTMLElement && cursor.current) { gsap.gsap.to("#" + cursor.current.id, { backgroundColor: "" + cursorBackgrounColor, duration: colorAnimationDuration, ease: colorAnimationEase }); } }); }); exclusionElements.forEach(function (el) { el.addEventListener('mouseenter', function (e) { if (e.target instanceof HTMLElement && cursor.current) { // @ts-ignore: Unreachable code error cursor.current.style.mixBlendMode = 'exclusion'; cursor.current.style.background = "" + exclusionBackgroundColor; } }); }); exclusionElements.forEach(function (el) { el.addEventListener('mouseleave', function (e) { if (e.target instanceof HTMLElement && cursor.current) { // @ts-ignore: Unreachable code error cursor.current.style.mixBlendMode = ''; cursor.current.style.background = "" + cursorBackgrounColor; } }); }); backgroundImageElements.forEach(function (el) { el.addEventListener('mouseenter', function (e) { if (e.target instanceof HTMLElement && cursorInner.current) { if (cursor.current) { // @ts-ignore: Unreachable code error if (cursor.current.style.mixBlendMode === 'exclusion') hasExclusionAlready = true; // @ts-ignore: Unreachable code error cursor.current.style.mixBlendMode = 'exclusion'; cursor.current.style.backgroundColor = 'transform'; } gsap.gsap.to("#" + cursorInner.current.id, { scale: 1, opacity: 1, background: "url(\"" + e.target.dataset['cursorBackgroundImage'] + "\")", filter: 'invert(1)', duration: backgroundImageAnimationDuration, ease: backgroundImageAnimationEase }); } }); }); backgroundImageElements.forEach(function (el) { el.addEventListener('mouseleave', function (e) { if (e.target instanceof HTMLElement && cursorInner.current) { if (cursor.current) { if (!hasExclusionAlready) { // @ts-ignore: Unreachable code error cursor.current.style.mixBlendMode = ''; cursor.current.style.backgroundColor = "" + cursorBackgrounColor; } else { cursor.current.style.backgroundColor = "" + exclusionBackgroundColor; } } gsap.gsap.to("#" + cursorInner.current.id, { scale: 0, opacity: 0, background: "", filter: 'none', duration: backgroundImageAnimationDuration }); } }); }); magneticElements.forEach(function (el) { el.addEventListener('mousemove', function (e) { var areatarget = e.target; gsap.gsap.to(areatarget, { x: (e.clientX - (areatarget.offsetLeft - window.pageXOffset) - areatarget.clientWidth / 2) * magneticAnimationAmount, y: (e.clientY - (areatarget.offsetTop - window.pageYOffset) - areatarget.clientHeight / 2) * magneticAnimationAmount, duration: magneticAnimationDuration, ease: magneticAnimationEase }); }); }); magneticElements.forEach(function (el) { el.addEventListener('mouseleave', function (e) { var areatarget = e.target; gsap.gsap.to(areatarget, { x: 0, y: 0, duration: magneticAnimationDuration, ease: magneticAnimationEase }); }); }); stickElements.forEach(function (el) { el.addEventListener('mouseenter', function () { return stickStatus = true; }); }); stickElements.forEach(function (el) { el.addEventListener('mouseleave', function () { return stickStatus = false; }); }); return function () { window.removeEventListener('mousemove', setFromEvent); document.body.removeEventListener('mouseenter', function () {}); document.body.removeEventListener('mouseleave', function () {}); sizeElements.forEach(function (el) { el.removeEventListener('mouseenter', function () {}); el.removeEventListener('mouseleave', function () {}); }); textElements.forEach(function (el) { el.removeEventListener('mouseenter', function () {}); el.removeEventListener('mouseleave', function () {}); }); colorElements.forEach(function (el) { el.removeEventListener('mouseenter', function () {}); el.removeEventListener('mouseleave', function () {}); }); exclusionElements.forEach(function (el) { el.removeEventListener('mouseenter', function () {}); el.removeEventListener('mouseleave', function () {}); }); backgroundImageElements.forEach(function (el) { el.removeEventListener('mouseenter', function () {}); el.removeEventListener('mouseleave', function () {}); }); magneticElements.forEach(function (el) { el.removeEventListener('mousemove', function () {}); el.removeEventListener('mouseleave', function () {}); }); stickElements.forEach(function (el) { el.removeEventListener('mouseenter', function () {}); el.removeEventListener('mouseleave', function () {}); }); }; }); useTicker(loop); return React__default.createElement("div", { ref: cursor, id: 'c-cursor', className: "c-cursor", style: { width: cursorSize, height: cursorSize, background: cursorBackgrounColor } }, React__default.createElement("div", { style: { color: cursorInnerColor }, ref: cursorInner, id: 'c-cursorInner', className: "c-cursor__inner" })); }; exports.Cursor = Cursor; //# sourceMappingURL=react-creative-cursor.cjs.development.js.map