Mouse Image Distortion
A website animation featuring an image distortion in a curved, using the sin function, React, React Three Fiber and Framer Motion
Olivier Larose
March 24, 2023
/
Beginner
/
Short
A cartoonish mouse trailing animation, made with React in a Next.js environment.
Live DemoSource codeVideo TutorialLet's start the project by creating a Next.js application. We can do that by running npx create-next-app@13.2.4 myApp
inside of a terminal.
Let's also create an /images
folder inside of the /public
folder and add the smiley image, you can add whatever image you'd like or found the one I used here.
We can delete everything in the index.js
and add our own HTML and CSS.
For the CSS, we're going to use CSS Module, so make sure to create a Home.module.css
file inside of the styles
folder. Thankfully, Next.js has built-in support for CSS Modules
Index.js
Home.mod...
1
import styles from '../styles/Home.module.css'2
3
export default function Home() {4
return (5
<div className={styles.main}>6
<div className={styles.container}>7
<img className={styles.img} src="/images/smiley.svg"></img>8
</div>9
</div>10
)11
}12
To create a trailing effect, it's going to be pretty easy. We'll detect the mouse movement and add a new div represening a circle at the cursor's position.
ref
to the image and the container.OnMouseMove
event on the container.div
element using Javascript and add it as a child of the container.top
and left
property of the image to move it.Index.js
Home.mod...
1
...2
3
const container = useRef();4
const img = useRef();5
6
const manageMouseMove = (event) => {7
const { clientX, clientY } = event8
const containerPosition = container.current.getBoundingClientRect();9
const x = clientX - containerPosition.x10
const y = clientY - containerPosition.y11
img.current.style.top = y + "px";12
img.current.style.left = x + "px";13
draw(x, y)14
}15
16
const draw = (x, y) => {17
const div = document.createElement("div");18
div.classList.add(styles['circle']);19
div.style.top = y + "px";20
div.style.left = x + "px";21
container.current.append(div);22
}23
24
return (25
<div className={styles.main}>26
<div ref={container} onMouseMove={(e) => {manageMouseMove(e)}} className={styles.container}>27
<img ref={img} className={styles.img} src="/images/smiley.svg"></img>28
</div>29
</div>30
)
Now that we have a nice trailing animation, we can add a final touch by removing some of the divs incrementely. It will also help the performance of the animation.
Here's the two ways we're going to remove the trail:
1
...2
3
const draw = (x, y) => {4
...5
container.current.append(div);6
7
if(container.current.childNodes.length > 25){8
erase();9
}10
else{11
setTimeout( () => {12
erase();13
}, 1500)14
}15
}16
17
const erase = () => {18
container.current.removeChild(container.current.childNodes[1])19
}20
A nice little cartoonish trail animation made in less than 50 lines of codes. Nice to know that we can simply create new divs and dynamically style them with css, while keeping great performance.
Hope you learned a lot :)
-Oli