Blob Cursor Effect

An interactive React component that adds a dynamic bubble effect, visually tracking cursor movement in real time.

1
// @ts-nocheck
2
'use client';
3
import { useTrail, animated } from '@react-spring/web';
4
import { useRef, useEffect, useCallback } from 'react';
5
6
import './BlobCursor.css';
7
8
const fast = { tension: 1200, friction: 40 };
9
const slow = { mass: 10, tension: 200, friction: 50 };
10
const trans = (x, y) => `translate3d(${x}px,${y}px,0) translate3d(-50%,-50%,0)`;
11
12
const BlobCursor = ({ blobType = 'circle', fillColor = '#fegefe' }) => {
13
const [trail, api] = useTrail(3, (i) => ({
14
xy: [0, 0],
15
config: i === 0 ? fast : slow,
16
}));
17
18
const ref = useRef<HTMLDivElement>(null);
19
const updatePosition = useCallback(() => {
20
if (ref.current) {
21
const rect = ref.current.getBoundingClientRect();
22
return { left: rect.left, top: rect.top };
23
}
24
return { left: 0, top: 0 };
25
}, []);
26
27
const handleMove = (e) => {
28
const { left, top } = updatePosition();
29
const x = e.clientX || (e.touches && e.touches[0].clientX);
30
const y = e.clientY || (e.touches && e.touches[0].clientY);
31
api.start({ xy: [x - left, y - top] });
32
};
33
34
useEffect(() => {
35
const handleResize = () => {
36
updatePosition();
37
};
38
39
window.addEventListener('resize', handleResize);
40
return () => {
41
window.removeEventListener('resize', handleResize);
42
};
43
}, [updatePosition]);
44
45
return (
46
<div className='container '>
47
<svg style={{ position: 'absolute', width: 0, height: 0 }}>
48
<filter id='blob'>
49
<feGaussianBlur in='SourceGraphic' result='blur' stdDeviation='30' />
50
<feColorMatrix
51
in='blur'
52
values='1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 35 -10'
53
/>
54
</filter>
55
</svg>
56
<div
57
ref={ref}
58
className='main'
59
onMouseMove={handleMove}
60
onTouchMove={handleMove}
61
>
62
{trail.map((props, index) => (
63
<animated.div
64
key={index}
65
style={{
66
transform: props.xy.to(trans),
67
borderRadius: blobType === 'circle' ? '50%' : '0%',
68
backgroundColor: fillColor,
69
}}
70
/>
71
))}
72
</div>
73
</div>
74
);
75
};
76
77
export default BlobCursor;
78

Installtion

1
npm install @react-spring/web
2

blobcursor css

1
.container {
2
width: 100%;
3
height: 100%;
4
}
5
6
.main > div {
7
position: absolute;
8
will-change: transform;
9
border-radius: 50%;
10
background: lightcoral;
11
box-shadow: 10px 10px 5px 0px rgba(0, 0, 0, 0.75);
12
opacity: 0.6;
13
}
14
15
.main > div:nth-child(1) {
16
width: 60px;
17
height: 60px;
18
}
19
20
.main > div:nth-child(2) {
21
width: 125px;
22
height: 125px;
23
}
24
25
.main > div:nth-child(3) {
26
width: 75px;
27
height: 75px;
28
}
29
30
.main > div::after {
31
content: '';
32
position: absolute;
33
top: 20px;
34
left: 20px;
35
width: 20px;
36
height: 20px;
37
border-radius: 50%;
38
background: rgba(255, 0, 0, 0.8);
39
}
40
41
.main > div:nth-child(2)::after {
42
top: 35px;
43
left: 35px;
44
width: 35px;
45
height: 35px;
46
}
47
48
.main > div:nth-child(3)::after {
49
top: 25px;
50
left: 25px;
51
width: 25px;
52
height: 25px;
53
}
54
55
.main {
56
position: absolute;
57
width: 100%;
58
height: 100%;
59
filter: url('#blob');
60
overflow: hidden;
61
background: transparent;
62
-webkit-touch-callout: none;
63
-webkit-user-select: none;
64
-khtml-user-select: none;
65
-moz-user-select: none;
66
-ms-user-select: none;
67
user-select: none;
68
cursor: default;
69
}