Canvas reactjs 重新渲染时闪烁

Canvas flickering when reactjs re-renders

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

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

这是我的渲染方法:

render: function() {
 var canvasStyle = {
   width: this.props.width
 };

 return (
   <canvas id="interactiveCanvas" style={canvasStyle}/>
 );
}

作为临时解决方案,我手动附加了我的 canvas 标签,没有 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 呈现此 canvas 标签。

知道如何解决这个问题吗?或者至少避免 reactjs 在只有绘制的框架发生变化时重新渲染这个 canvas 。

重新渲染整棵树不应导致 canvas 闪烁。但是,如果您认为重新渲染导致了此问题,则可以在不想更新时使用 shouldComponentUpdate 生命周期函数和 return false。

https://facebook.github.io/react/docs/component-specs.html#updating-shouldcomponentupdate

例如:

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

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

但是我无法重现您抱怨的闪烁问题。你的整棵树是否渲染得太频繁了?在这种情况下,上述将修复您的 canvas,但您应该查看重新渲染整棵树的次数和频率,并修复那里的任何问题。

我花了一些时间观察你的建议,我发现这种闪烁是由于我正在访问 canvas DOM 元素并更改 canvas.width 和 canvas.height 每次调用 onComponentDidUpdate 时。

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

如此处所述:https://facebook.github.io/react/tips/dom-event-listeners.html 我附加了调整大小事件,现在我仅从我的 resizeHandler 更改 canvas 属性。

我遇到了同样的问题。我使用了 react-konva 库,我的组件结构看起来像这样: canvas 有一个背景图像 <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;