如何将React-Konva的Stage宽高设置为与其容器div一致?
让React-Konva Stage与父容器尺寸同步的实现方案
我来帮你搞定这个问题!要让React-Konva的Stage和父级drawing-area容器尺寸保持一致,核心是动态获取容器的尺寸并实时更新Stage的宽高,下面是具体的实现步骤和代码:
1. 核心思路
- 使用
useRef获取drawing-area容器的DOM引用 - 用
useState存储Stage的宽高状态 - 通过
ResizeObserver监听容器尺寸变化(比监听window resize更精准,能捕捉容器自身布局变化) - 在组件初始化和容器尺寸变化时,更新Stage的宽高
2. 完整实现代码
import { useState, useEffect, useRef } from 'react'; import { Stage, Layer } from 'react-konva'; import { Row, Col } from 'antd'; // 匹配你代码中用到的Ant Design组件 const Canvas = props => { const [stageSize, setStageSize] = useState({ width: 0, height: 0 }); const drawingAreaRef = useRef(null); useEffect(() => { const updateStageSize = () => { if (drawingAreaRef.current) { const { offsetWidth, offsetHeight } = drawingAreaRef.current; setStageSize({ width: offsetWidth, height: offsetHeight }); } }; // 组件初始化时先获取一次容器尺寸 updateStageSize(); // 创建ResizeObserver监听容器尺寸变化 const observer = new ResizeObserver(updateStageSize); drawingAreaRef.current && observer.observe(drawingAreaRef.current); // 组件卸载时清理监听,避免内存泄漏 return () => { drawingAreaRef.current && observer.unobserve(drawingAreaRef.current); }; }, []); // 避免初始尺寸为0时Stage渲染异常,添加加载状态 if (stageSize.width === 0 || stageSize.height === 0) { return ( <Row> <Col xs={12} className="canvas-container"> <div className="drawing-area">Loading canvas...</div> </Col> </Row> ); } return ( <Row> <Col xs={12} className="canvas-container"> <div className="drawing-area" ref={drawingAreaRef}> <Stage width={stageSize.width} height={stageSize.height}> <Layer> <BoxSurface/> <UserText text={props.text}/> <DesignImage image={props.image}/> <Handler image={props.image}/> </Layer> </Stage> </div> </Col> </Row> ); }; export default Canvas;
3. 关键注意事项
- 确保父容器有明确尺寸:给
drawing-area添加CSS样式,让它的尺寸可被正确计算,比如:.drawing-area { width: 100%; height: 100%; overflow: hidden; /* 如果父容器canvas-container有固定宽高,这里会自动继承;响应式场景下也会跟着变化 */ } - ResizeObserver兼容性:现代浏览器都原生支持ResizeObserver,若需兼容极旧浏览器,可添加对应的polyfill(大部分项目不需要)
- 状态更新的时机:通过ResizeObserver能精准捕获容器的尺寸变化,包括父容器布局调整、窗口缩放等场景
这样你的Stage就会始终和drawing-area容器的尺寸保持一致,各种场景下都能自动适配~
内容的提问来源于stack exchange,提问作者0xh8h
相关产品推荐
相关产品推荐

