gpt4 book ai didi

reactjs - 如何通过一劳永逸地重新渲染来修复图像闪烁?

转载 作者:行者123 更新时间:2023-12-03 21:03:32 25 4
gpt4 key购买 nike

我正在尝试使用 ReactJS 制作一个基于 Sprite 的小型游戏。绿龙(取自 HMMII)飞过六边形场,它的行为取决于鼠标点击。 Sprite 根据一个特别选择的时间常数 - 170ms 的速度相互改变。更准确地说:有一个代表龙的 div,它的属性(顶部、左侧、宽度、高度和背景图像)总是在变化。

在开发的第一阶段,通过重新渲染图像,我遇到了令人讨厌的闪烁和闪烁。怎样才能避免呢?

下面描述了我使用 Surge 制作的一些预览的多种方式。在 Google Chrome 中观看效果最强,但在 Firefox 中也有问题。

0)起初我尝试使用基于@keyframes的CSS动画,但由于淡入淡出效果不佳。而且我根本不需要任何淡入淡出效果,我需要快速重新渲染。

1)这是最直接的尝试。单击特定字段后,componentWillReceiveProps 将创建步骤列表,然后所有这些步骤都将一致执行。我也尝试使用 requestAnimationFrame 而不是 setTimeout 但也有同样的麻烦。

    makeStep() {
const {steps} = this.state;

this.setState((prevState, props) => ({
steps: steps.slice(1),
style: {...}
}));
}


render() {
const {steps, style} = this.state;
steps.length ? setTimeout(this.makeStep, DRAGON_RENDER_TIME):
this.props.endTurn();

return (<div id="dragon" style={style}></div>);
}


结果如下: http://streuner.surge.sh/如您所见,龙经常通过发射和着陆而消失,它会跳过一些 Sprite 飞行。

2)我试图测试文章中描述的方法:
https://itnext.io/stable-image-component-with-placeholder-in-react-7c837b1ebee

在这种情况下,我已将带有背景图像的 div 更改为包含显式 img 的其他 div。一开始,this.state.isLoaded 为false,不会出现新的 Sprite 。只有在使用 onLoad 方法加载图像后才会出现。此外,我尝试将 refs 与尝试监 View 像的完整属性一起使用,但这总是正确的 - 可能是因为图像的大小非常小。
    setLoaded(){
this.setState((prevState, props) => ({
isLoaded: true
}));
}


render() {
const {isLoaded, steps, style} = this.state;
if(isLoaded) {
steps.length ? setTimeout(this.makeStep, DRAGON_RENDER_TIME):
this.props.endTurn();
}

return (<div id="wrap" style={{top:style.top, left:style.left}} >
<img id="dragon" alt="" src={style.src} onLoad={this.setLoaded}
style={{width:style.width,
height: style.height,
visibility: isLoaded ? "visible": "hidden"}}/>
</div>);
}


结果如下: http://streuner2.surge.sh/没有更多的 Sprite 跳跃,但闪烁效果比第一种情况强得多。

3)也许这是我最好的尝试。我已阅读此建议: https://github.com/facebook/react-native/issues/981并决定立即渲染所有步骤图像,但只有不透明度 = 1 的一个,其他不透明度 = 0。
    makeStep(index) {
const {steps} = this.state;

this.setState((prevState, props) => ({
index: index + 1,
steps: steps.map( (s, i) => ({...s, opacity: (i !== index) ? 0: 1}))
}));
}


render() {
const {index, steps} = this.state;

(index < steps.length) ?
setTimeout(() => this.makeStep(index), DRAGON_RENDER_TIME):
this.props.endTurn();

return ([steps.map((s, i) =>
<div className="dragon" key={i} style={s}></div>)]);
}

可以在这里看到结果: http://streuner3.surge.sh/通过重新渲染所有 Sprite 开始新的飞行,只有一个闪烁。但代码在我看来更人为。

我想强调的是,行为总是取决于浏览器,在 Firefox 中要好得多。同一浏览器中的各种苍蝇也存在差异:有时没有闪烁效果,但在大多数情况下不幸的是。也许我不明白在浏览器中重新渲染图像的任何基本概念。

最佳答案

我认为您应该将注意力从动画本身转移到 React 中更多地关注重新渲染,每次更改 Image 组件状态或 Prop 时,它都在重新渲染。在 React 文档中阅读生命周期方法和重新渲染。

您更改状态的速度非常快(在您的情况下几乎每秒 6 次),所以我认为某些浏览器的 Image 组件重新渲染速度不够快。尝试移出更新如此之快的图像状态变量,一切都会好起来的

关于reactjs - 如何通过一劳永逸地重新渲染来修复图像闪烁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56091300/

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