I'm new to react and I'm trying to get this cursor effect on my landing page, but I haven't been able to make it without using jquery... I have looked at react SyntheticEvents, but I don't know how to use them right.
Here is the effect that I want to achieve, but in react:
$(document)
.mousemove(function(e) {
$('.cursor')
.eq(0)
.css({
left: e.pageX,
top: e.pageY
});
setTimeout(function() {
$('.cursor')
.eq(1)
.css({
left: e.pageX,
top: e.pageY
});
}, 100);
})
body{
background:black;
}
h1{
color:white;
}
* {
cursor: none;
}
.cursor {
position: fixed;
height: 10px;
width: 10px;
border-radius: 50%;
transform: translateX(-50%) translateY(-50%);
pointer-events:none;
}
.cursors .cursor:nth-child(1) {
background-color: #3a26fd;
z-index: 100002;
}
.cursors .cursor:nth-child(2) {
background-color: #f3f3f3;
z-index: 100001;
height: 9px;
width: 9px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="cursors">
<div class='cursor'></div>
<div class='cursor'></div>
<div class='cursor'></div>
</div>
<h1>Custom cursor</h1>
First, a couple of notes:
I'm assuming you use Babel to transpile JSX and to be able to use ES2015 arrow functions. If not, please update your question and I'll update my answer.
Next, you don't need three elements of the cursor class. The code suggests you only use two elements. The blue one which I'll call mainCursor and the white one - trailingCursor.
Also, I didn't implement the eq function from jQuery, but in this example we are sure document.getElementByClassName will return 2 elements, so I'm not including checks for null.
The React way of implementing requested behavior is:
That being said, here's the ported version of the functionality from your question. I've provided a runnable snippet.
class App extends React.Component {
// we keep track of x and y coordinates for the blue circle - the main one
// and the trailing circle - the white one
// for simplicity, they are initialzed to (0, 0), the top left corner of the viewport
state = {
xMain: 0,
yMain: 0,
xTrailing: 0,
yTrailing: 0,
}
handleMouseMove = (e) => {
// Using pageX and pageY will cause glitching when you scroll the window down
// because it measures the distance from the top left rendered corner, not
// top left visible corner
const { clientX, clientY } = e;
// we set the main circle coordinates as soon as the mouse is moved
this.setState({
xMain: clientX,
yMain: clientY,
}, () => {
// this callback is invoked after the first setState finishes
//
// here we schedule saving the trailing coordinates in state 100ms
// after the main coordinates have been set to simulate the trailing
setTimeout(() => {
this.setState({
xTrailing: clientX,
yTrailing: clientY,
})
}, 100);
})
}
render = () => {
// we retrieve coordinates from state
const {
xMain,
yMain,
xTrailing,
yTrailing
} = this.state;
return (
// we need a container that has a definite height, 800px in my example
// this is to make sure it leaves enough room for mouse movement to happen and trigger the event handler
//
// also, you don't need the event listener on both your cursor elements, only on the container
<div
className='container'
onMouseMove={e => this.handleMouseMove(e)}
>
<div className='cursors'>
// this below is the main cursor
// we set its style inline with coordinates from state
<div
className='cursor'
style={{
left: xMain,
top: yMain,
}}
/>
// this below is the trailing cursor
<div
className='cursor'
style={{
left: xTrailing,
top: yTrailing,
}}
/>
</div>
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById('root'));
* {
cursor: none;
}
.container {
background: black;
min-height: 800px;
}
.cursor {
position: fixed;
height: 10px;
width: 10px;
border-radius: 50%;
transform: translateX(-50%) translateY(-50%);
pointer-events:none;
}
.cursors .cursor:nth-child(1) {
background-color: #3a26fd;
z-index: 100002;
}
.cursors .cursor:nth-child(2) {
background-color: #f3f3f3;
z-index: 100001;
height: 9px;
width: 9px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
</head>
<body>
<div id="root"></div>
</body>
</html>