reactjs - 在 React 中使画布适合屏幕
问题描述
所以我有这个代码库:
import React, { useEffect, useRef, useState } from 'react';
function App() {
const container = useRef(null);
const canvas = useRef(null);
const [ctx, setCtx] = useState(undefined);
useEffect(() => {
setCtx(canvas.current.getContext("2d"));
}, []);
useEffect(() => {
if (!ctx) return;
ctx.fillStyle = 'green';
ctx.fillRect(0, 0, canvas.current.width, canvas.current.height);
}, [ctx]);
return (
<div
style={{
height: "100vh",
display: "flex",
flexDirection: "column",
padding: 8,
position: "relative",
}}
>
<header>
Some Header
</header>
<div style={{ margin: 40, flex: '1 1' }} ref={container}>
<canvas ref={canvas} />
</div>
</div>
);
}
export default App;
这是放置在容器 div 内的画布元素的非常基本的示例。
我想要做的是根据用户的屏幕调整画布的宽度和高度(并使其具有响应性)。
所以我发现了两个选择:
使用window.addEventListener('resize', ...)
或使用ResizeObserver
。
我尝试了它们,但没有任何成功,这就是我试图做的:
import React, { useEffect, useRef, useState } from 'react';
function App() {
const container = useRef(null);
const canvas = useRef(null);
const [ctx, setCtx] = useState(undefined);
const [size, setSize] = useState([0, 0]);
useEffect(() => {
const resize = () => {
const { offsetWidth, offsetHeight } = container.current;
canvas.current.width = offsetWidth;
canvas.current.height = offsetHeight;
setSize([offsetWidth, offsetHeight]);
setCtx(canvas.current.getContext('2d'));
};
resize();
window.addEventListener('resize', resize);
return () => window.removeEventListener('resize', resize);
}, []);
useEffect(() => {
if (!ctx) return;
ctx.fillStyle = 'green';
ctx.fillRect(0, 0, size[0], size[1]);
}, [ctx, size]);
return (
<div
style={{
height: "100vh",
display: "flex",
flexDirection: "column",
padding: 8,
position: "relative",
}}
>
<header>
Some Header
</header>
<div style={{ margin: 40, flex: '1 1' }} ref={container}>
<canvas ref={canvas} style={{ width: size[0], height: size[1] }} />
</div>
</div>
);
}
export default App;
但由于某种原因,它使画布的高度在每个调整大小循环中都更大。
为什么会这样,我该如何解决?
解决方案
如果您使用画布包没有问题,您可以使用react-konva
它可以很好地处理响应性。
因此,您所要做的就是在调整窗口大小时更改高度和宽度,并将它们作为属性发送。
...
useEffect(() => {
const checkSize = () => {
setSize({
width: window.innerWidth,
height: window.innerHeight
});
};
window.addEventListener("resize", checkSize);
return () => window.removeEventListener("resize", checkSize);
}, []);
...
return (
<Stage
width={size.width}
height={size.height}
>
...
</Stage>
)
...
演示:codesandbox
推荐阅读
- android - 创建自定义复杂的xml形状android
- encode - 具有多组 SPS 和 PPS 且采用 avcc 编码的分段 MP4 视频
- excel - 函数内部有一个数组,返回错误 1004
- python - Python:由数据框和列表组成的 IF 语句
- arrays - 使用不同级别的位置过滤器更新嵌套对象 - MongoDb 更新
- python - 我想用 self 参数线程化一个函数
- python - 从服务器上运行的 Jupyter 笔记本链接到外部站点
- bash - 为什么 $RANDOM 最大值是 32767 而不是 65535?
- ios - 为什么 TableView 单元格中的垂直堆栈视图不能动态生成高度?
- java - 当有单个值或y轴值相同时,Hellocharts android库不渲染图表