reactjs - 调整大小时画布反应组件闪烁
问题描述
当我调整画布组件的大小时,它会闪烁。我不太确定为什么会这样。当画布长度和宽度发生变化时,会发生调整大小。
这是我的组件:
const Cargo = styled.canvas`
width: ${props => props.width}px;
height: ${props => props.height}px;
margin-left: ${props => props.marginLeft}px;
position: relative;
`;
const Canvas = () => {
const canvasRef = useRef(null);
useEffect(() => {
const canvas = canvasRef.current;
const img = new Image();
const ctx = canvas.getContext('2d');
if(!canvas) {
return;
}
const draw = () => {
img.src = `${process.env.PUBLIC_URL}/images/${(cargoState.cargo_type).toLowerCase()}.jpg`;
img.onload = function () {
canvas.width = this.naturalWidth;
canvas.height = this.naturalWidth;
ctx.drawImage(img, 0, 0, this.width, this.height);
};
}
draw();
},[]);
return (
<>
<Cargo ref={canvasRef} style={{marginLeft: marginLeft}} height={cargoHeight} width={cargoWidth} />
</>
)
}
解决方案
闪烁是由于两个原因:
- 在每张图中创建一个新图像是一项昂贵的操作,所以最好使用参考,这给我带来了很多优化
- 大小的变化可能有点突然,特别是如果它是用鼠标滚轮完成的。所以最好是使用requestAnimationFrame。
如果您只执行第 1 步,则不会出现闪烁。
代码如下所示:
const canvasRef = useRef(null);
const requestRef = useRef();
const image = useRef(null);
const [cargoHeight, setCargoHeight] = useState(100);
const [cargoWidth, setCargoWidth] = useState(100);
const draw = () => {
const canvas = canvasRef.current;
const img = new Image();
const ctx = canvas.getContext("2d");
canvas.width = image.current.width;
canvas.height = image.current.height;
ctx.drawImage(
image.current,
0,
0,
image.current.width,
image.current.width
);
};
useLayoutEffect(() => {
requestRef.current = requestAnimationFrame(draw);
return () => window.cancelAnimationFrame(requestRef.current);
}, [cargoHeight, cargoWidth]);
return (
<div className="App">
<img
src={
"https://www.tuexperto.com/wp-content/uploads/2020/01/png.jpg.webp"
}
ref={image}
style={{ display: "none" }}
/>
<Cargo ref={canvasRef} height={cargoHeight} width={cargoWidth} />
<button onClick={() => setCargoHeight(cargoHeight + 50)}>height</button>
<button onClick={() => setCargoWidth(cargoWidth + 50)}>width</button>
</div>
);
带有解决方案和完整示例的代码框
推荐阅读
- azure - IOT Central Connected Field Service - 发送命令
- google-bigquery - Issue with Implementing a Helpdesk Chatbot with Dialogflow & BigQuery ML
- azure-cosmosdb - Are CosmosDB attachments (still) a good way to store payloads larger than the document limit of 2MB?
- python - hadoop filesystem open file and skip first line
- ios - updateSearchResults function is not being called when searchBar is touched
- apache-kafka - How to make kafka connect to pick up messages from last failure
- xamarin.forms - 如何使用 Sqlite.net 在 xamarin.forms 中的 ObservableCollection 中保护 ObservableCollection
- android - Data not being fetched from firestore database
- alias - 在这种情况下如何为记录创建别名?
- python - 重新排序字典列表中的字典键