我是新来的反应者,我正在尝试在我的登录页面上获得此光标效果,但是如果不使用jquery我就无法做到这一点...我已经看过反应SyntheticEvents ,但我不知道如何正确使用它们。
这是我想要实现的效果,但是在反应中:
$(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>
答案 0 :(得分:1)
以前的解决方案对于不需要性能的人来说效果很好。
我的解决方案是使用requestAnimationFrame而不是setTimeout和ref来缩短绘制时间和使动画更流畅,此外,使用转换代替绝对位置通常会提供更好的FPS。
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
mouseX: 0,
mouseY: 0,
trailingX: 0,
trailingY: 0,
};
this.cursor = React.createRef();
this.cursorTrailing = React.createRef();
this.animationFrame = null;
}
componentDidMount() {
document.addEventListener('mousemove', this.onMouseMove);
this.moveCursor();
}
componentWillUnmount() {
document.removeEventListener('mousemove', this.onMouseMove)
cancelAnimationFrame(this.animationFrame);
}
onMouseMove = (evt) => {
const { clientX, clientY } = evt;
this.setState({
mouseX: clientX,
mouseY: clientY,
});
}
moveCursor = () => {
const { mouseX, mouseY, trailingX, trailingY } = this.state;
const diffX = mouseX - trailingX;
const diffY = mouseY - trailingY;
// Number in expression is coeficient of the delay. 10 for example. You can play with it.
this.setState({
trailingX: trailingX + diffX / 10,
trailingY: trailingY + diffY / 10,
},
() => {
// Using refs and transform for better performance.
this.cursor.current.style.transform = `translate3d(${mouseX}px, ${mouseY}px, 0)`;
this.cursorTrailing.current.style.transform = `translate3d(${trailingX}px, ${trailingY}px, 0)`;
this.animationFrame = requestAnimationFrame(this.moveCursor);
});
}
render = () => {
return (
<div className="container">
<div className="cursors">
<div
className="cursor"
ref={this.cursor}
/>
<div
className='cursor'
ref={this.cursorTrailing}
/>
</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>
答案 1 :(得分:0)
首先,请注意以下几点:
我假设您使用Babel来转译JSX并能够使用ES2015箭头功能。如果没有,请更新您的问题,我会更新我的答案。
接下来,您不需要 cursor 类的三个元素。该代码建议您仅使用两个元素。我称之为蓝色的 mainCursor 和白色的 trailingCursor 。
此外,我没有实现jQuery的eq函数,但是在此示例中,我们确定 document.getElementByClassName 将返回2个元素,因此我不包括对null的检查。
实现请求的行为的React方法是:
话虽这么说,这是您问题中功能的移植版本。我提供了一个可运行的代码段。
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>