问题描述
我正在使用此反应代码在主光标之后获取自定义光标。动画是使用 gsap 和 lerp 函数完成的。但是动画不是无缝的,chrome 性能监视器显示 cpu 使用率超过 100%。请帮我解决这个问题。我参考了这个视频链接来获取光标动画:https://www.youtube.com/watch?v=MEO6yQLAgKw&list=PLtSHrBhMos7hXeImRWnnC38mdYp_4c333&index=2&t=630s
import gsap from 'gsap';
import React,{Component} from 'react';
import './cursor.scss';
class Cursor extends Component{
constructor(props){
super(props);
this.state={
x : 0,y : 0
};
this.cursor = React.createRef();
this.cursorConfigs = {
x: { prevIoUs: 0,current: 0,amt: 0.2 },y: { prevIoUs: 0,};
this.lerp = (a,b,n) => (1 - n) * a + n * b;
}
componentDidMount(){
window.addEventListener("mousemove",e=> {
this.setState({
x: e.pageX,y:e.pageY
})
});
this.cursor.current.style.opacity = 0;
this.onMouseMoveEv = () => {
this.cursorConfigs.x.prevIoUs = this.cursorConfigs.x.current = this.state.x;
this.cursorConfigs.y.prevIoUs = this.cursorConfigs.y.current = this.state.y;
gsap.to(this.cursor.current,{
duration: 1,ease: "Power4.eaSEOut",opacity: 1,});
window.removeEventListener("mousemove",this.onMouseMoveEv);
requestAnimationFrame(() =>this.render());
};
window.addEventListener("mousemove",this.onMouseMoveEv);
}
render(){
this.cursorConfigs.x.current = this.state.x;
this.cursorConfigs.y.current = this.state.y;
for (const Key in this.cursorConfigs){
this.cursorConfigs[Key].prevIoUs = this.lerp(
this.cursorConfigs[Key].prevIoUs,this.cursorConfigs[Key].current,this.cursorConfigs[Key].amt
);
}
console.log(this.cursorConfigs.x.prevIoUs,this.cursorConfigs.x.current)
var styles = {
transform:`translateX(${this.cursorConfigs.x.prevIoUs}px) translateY(${this.cursorConfigs.y.prevIoUs}px)`
}
requestAnimationFrame(() =>this.render());
return(
<div className="cursor" ref={this.cursor} style={styles}>
<div className="cursor-media">
</div>
</div>
)
}
}
export default Cursor;```
解决方法
您实际上不需要在每次鼠标移动时更新。考虑去抖动 setState
示例:
// delay in ms
function debounced(delay,fn) {
let timerId;
return function (...args) {
if (timerId) {
clearTimeout(timerId);
}
timerId = setTimeout(() => {
fn(...args);
timerId = null;
},delay);
};
}
function handler(e) {
this.setState({
x: e.pageX,y: e.pageY,});
};
window.addEventListener("mousemove",debounced(200,handler));