gpt4 book ai didi

javascript - 如何跨多个 React Redux 组件使用 requestAnimationFrame 实现游戏循环?

转载 作者:搜寻专家 更新时间:2023-10-30 21:34:21 26 4
gpt4 key购买 nike

努力想出解决问题的最佳方法。我可以使用 requestAnimationFrame 的递归调用来实现游戏循环:

export interface Props {
name: string;
points: number;
onIncrement?: () => void;
onDecrement?: () => void;
}

class Hello extends React.Component<Props, object> {

constructor(props: Props) {
super(props);
}

render() {
const { name, points, onIncrement, onDecrement } = this.props;

return (
<div className="hello">
<div className="greeting">
Hello {name + points}
</div>
<button onClick={onDecrement}>-</button>
<button onClick={onIncrement}>+</button>
</div>
);
}

componentDidMount() {
this.tick();
}

tick = () => {
this.props.onIncrement();
requestAnimationFrame(this.tick)
}

}

但是如果我想要在每一帧上怎么办:

  • Component1 做 X
  • 组件 2 做 Y
  • Component3做Z

我可以在每个组件中有另一个循环,但我的理解是让多个 requestAnimationFrame 循环运行是不好的做法,这会严重影响性能。

所以我在这里迷路了。我怎样才能让另一个组件使用相同的循环? (如果那是最好的方法!)

最佳答案

您需要一个调用 requestAnimationFrame 并迭代 refs 数组的父组件需要在每个周期更新的子组件,调用它的 update (或者你想怎么调用它)方法:

class ProgressBar extends React.Component {

constructor(props) {
super(props);

this.state = {
progress: 0,
};
}

update() {
this.setState((state) => ({
progress: (state.progress + 0.5) % 100,
}));
}

render() {
const { color } = this.props;
const { progress } = this.state;

const style = {
background: color,
width: `${ progress }%`,
};

return(
<div className="progressBarWrapper">
<div className="progressBarProgress" style={ style }></div>
</div>
);
}
}

class Main extends React.Component {

constructor(props) {
super(props);

const progress1 = this.progress1 = React.createRef();
const progress2 = this.progress2 = React.createRef();
const progress3 = this.progress3 = React.createRef();

this.componentsToUpdate = [progress1, progress2, progress3];
this.animationID = null;
}

componentDidMount() {
this.animationID = window.requestAnimationFrame(() => this.update());
}

componentWillUnmount() {
window.cancelAnimationFrame(this.animationID);
}

update() {
this.componentsToUpdate.map(component => component.current.update());

this.animationID = window.requestAnimationFrame(() => this.update());
}

render() {
return(
<div>
<ProgressBar ref={ this.progress1 } color="magenta" />
<ProgressBar ref={ this.progress2 } color="blue" />
<ProgressBar ref={ this.progress3 } color="yellow" />
</div>
);
}
}

ReactDOM.render(<Main />, document.getElementById('app'));
body {
margin: 0;
padding: 16px;
}

.progressBarWrapper {
position: relative;
width: 100%;
border: 3px solid black;
height: 32px;
box-sizing: border-box;
margin-bottom: 16px;
}

.progressBarProgress {
position: absolute;
top: 0;
left: 0;
height: 100%;
}
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="app"></div>

不过请记住,如果您尝试做一些过于复杂的事情并且想要达到 60 fps,React 可能不是适合使用的工具。

此外,setState is asynchronous ,因此在调用它时,您只是将更新推送到 React 将在某个时刻处理的队列,这实际上可能发生在下一帧或更晚的时候。

我分析了这个简单的例子,看看是否是这种情况,实际上不是。更新被添加到队列中 (enqueueSetState),但工作是立即完成的:

Example app profiling result

但是,我怀疑在 React 有更多更新要处理的真实应用程序中,或者在 React 的 future 版本中具有时间切片、带优先级的异步更新等功能......渲染实际上可能发生在不同的帧中。

关于javascript - 如何跨多个 React Redux 组件使用 requestAnimationFrame 实现游戏循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54066805/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com