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;
我在使用 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;