circledot-cursor
Version:
A custom cursor component for React
97 lines (88 loc) • 3.58 kB
JavaScript
import { useEffect } from 'react';
function styleInject(css, ref) {
if ( ref === undefined ) ref = {};
var insertAt = ref.insertAt;
if (typeof document === 'undefined') { return; }
var head = document.head || document.getElementsByTagName('head')[0];
var style = document.createElement('style');
style.type = 'text/css';
if (insertAt === 'top') {
if (head.firstChild) {
head.insertBefore(style, head.firstChild);
} else {
head.appendChild(style);
}
} else {
head.appendChild(style);
}
if (style.styleSheet) {
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}
}
var css_248z = "body{cursor:none!important}.cursor-dot{background-color:#ff0;border-radius:50%;height:5px;left:0;pointer-events:none;position:fixed;top:0;transform:translate(-50%,-50%);transition:opacity .2s ease;width:5px;z-index:99999}.cursor-dot-hidden{opacity:0}.cursor-circle{border:2px solid #5a5a01;border-radius:50%;box-sizing:border-box;height:30px;left:0;pointer-events:none;position:fixed;top:0;transform:translate(-50%,-50%);transition:all .1s ease;width:30px;z-index:99998}.cursor-circle.hovered{box-sizing:border-box;margin:0;padding:0;transform:none;transition:all .2s ease}.social-button,a,button{cursor:none!important}";
styleInject(css_248z);
const CustomCursor = () => {
useEffect(() => {
const cursorDot = document.createElement('div');
const cursorCircle = document.createElement('div');
cursorDot.className = 'cursor-dot';
cursorCircle.className = 'cursor-circle';
document.body.appendChild(cursorDot);
document.body.appendChild(cursorCircle);
let position = {
x: 0,
y: 0
};
let isHovered = false;
const updatePosition = e => {
position.x = e.clientX;
position.y = e.clientY;
if (!isHovered) {
cursorDot.style.left = `${position.x}px`;
cursorDot.style.top = `${position.y}px`;
cursorCircle.style.left = `${position.x}px`;
cursorCircle.style.top = `${position.y}px`;
}
};
const handleMouseEnter = e => {
isHovered = true;
cursorDot.classList.add('cursor-dot-hidden');
cursorCircle.classList.add('hovered');
const rect = e.target.getBoundingClientRect();
const computedStyle = window.getComputedStyle(e.target);
const isIcon = e.target.tagName === 'IMG' || computedStyle.borderRadius === '50%';
Object.assign(cursorCircle.style, {
width: `${rect.width}px`,
height: `${rect.height}px`,
borderRadius: isIcon ? '50%' : computedStyle.borderRadius,
left: `${rect.left}px`,
top: `${rect.top}px`,
border: '2px solid yellow'
});
};
const handleMouseLeave = () => {
isHovered = false;
cursorDot.classList.remove('cursor-dot-hidden');
cursorCircle.classList.remove('hovered');
cursorCircle.style = '';
};
window.addEventListener('mousemove', updatePosition);
document.querySelectorAll('button, a, .social-button').forEach(target => {
target.addEventListener('mouseenter', handleMouseEnter);
target.addEventListener('mouseleave', handleMouseLeave);
if (window.getComputedStyle(target).position === 'static') {
target.style.position = 'relative';
}
});
return () => {
window.removeEventListener('mousemove', updatePosition);
cursorDot.remove();
cursorCircle.remove();
};
}, []);
return null;
};
export { CustomCursor, CustomCursor as default };
//# sourceMappingURL=index.js.map