reactjs重新渲染时画布闪烁

Canvas flickering when reactjs re-renders

本文关键字:闪烁 布闪烁 新渲染 reactjs      更新时间:2023-09-26

我在一起使用React JS和canvas时遇到了问题。

一切似乎都很顺利,但当调用render方法时,由于我的应用程序画布的其他部分发生了变化,会闪烁。react似乎是将其重新附加到DOM中(可能是因为我在上面播放动画,每次绘制的帧都不同)。

这是我的渲染方法:

render: function() {
 var canvasStyle = {
   width: this.props.width
 };
 return (
   <canvas id="interactiveCanvas" style={canvasStyle}/>
 );
}

作为一个临时解决方案,我手动附加画布标签,不需要reactjs:

render: function() {
var canvasStyle = {
  width: this.props.width
};
return (
  <div id="interactivediv3D">
  </div>
);
}

然后:

componentDidMount: function() {
var canvasStyle = {
  width: this.props.width
};
var el = document.getElementById('interactivediv3D');
el.innerHTML = el.innerHTML + 
    '<canvas id="interactive3D" style={'+canvasStyle+'}/>';
 },

而且效果很好。但我认为这不是一种干净的方式,最好使用reactjs来渲染这个画布标签。

你知道我该怎么解决这个问题吗?或者至少避免了reactjs在只有绘制的帧发生变化时重新渲染此画布。

我考虑到你的建议,花了一些时间进行观察,发现这种闪烁是由我访问画布DOM元素并在每次调用onComponentDidUpdate时更改canvas.width和canvas.height引起的。

我需要手动更改此属性,因为在渲染时我还不知道canvas.width。我用"100%"填充样式宽度,渲染后我查看"canvas.clientWidth"以提取像素值。

如下所述:https://facebook.github.io/react/tips/dom-event-listeners.html我附加了resize事件,现在我只从resizeHandler更改画布属性。

重新渲染整个树不会导致画布闪烁。但是,如果您认为重新渲染导致了此问题,则可以使用shouldComponentUpdate生命周期函数,并在不想更新时返回false。

https://facebook.github.io/react/docs/component-specs.html#updating-应该组件更新

例如:

shouldComponentUpdate: function(nextProps, nextState) {
    return false;
}

任何定义了上述功能的组件都不会运行render一次以上(在组件安装时)。

然而,我无法复制你抱怨的闪烁问题。您的整棵树渲染是否过于频繁?在这种情况下,以上内容将修复画布,但您应该查看重新渲染整个树的次数和频率,并修复其中的任何问题。

我也遇到了同样的问题。我使用了react-konva库,我的组件结构看起来是这样的:画布有一个背景图像<SelectedImage />,每当任何状态属性更改时,它都会弹出
初始代码

import React, { useState } from "react";
import { Stage, Layer, Image } from "react-konva";
import useImage from "use-image";
function SomeComponent() {
    const [imgWidth, setImgWidth] = useState(0);
    const [imgHeight, setImgHeight] = useState(0);
    //...and other state properties
    const SelectedImage = () => {
        const [image] = useImage(imgSRC);
        if (imgWidth && imgHeight) {
            return <Image image={image} width={imgWidth} height={imgHeight} />;
        }
        return null;
    };
    return (
        <div>
            <Stage width={imgWidth} height={imgHeight}>
                <Layer>
                    <SelectedImage />
                    {/* some other canvas components*/}
                </Layer>
            </Stage>
        </div>
    );
}
export default SomeComponent;

解决方案
问题出现在SomeComponent的错误结构中,其中一个组件在另一个内部初始化。在我的案例中,它是SomeComponent内部的<SelectedImage />。我把它拿到一个单独的文件里,闪烁消失了
这是一个正确的结构

SelectedImage.js

import React from "react";
import { Image } from "react-konva";
import useImage from "use-image";
function SelectedImage({ width, height, imgSRC }) {
    const [image] = useImage(imgSRC);
    if (width && height) {
        return <Image image={image} width={width} height={height} />;
    }
    return null;
}
export default SelectedImage;

SomeComponent.js

import React, { useState } from "react";
import { Stage, Layer, Image } from "react-konva";
import SelectedImage from "./SelectedImage";
function SomeComponent() {
    const [imgWidth, setImgWidth] = useState(0);
    const [imgHeight, setImgHeight] = useState(0);
    //...and other state properties
    return (
        <div>
            <Stage width={imgWidth} height={imgHeight}>
                <Layer>
                    <SelectedImage width={imgWidth} height={imgHeight} imgSRC={imgSRC} />
                    {/* some other canvas components*/}
                </Layer>
            </Stage>
        </div>
    );
}
export default SomeComponent;