在 React 中根据窗口大小进行渲染
介绍
展示窗尺寸
要显示窗口的宽度和高度,并在更改时让组件进行渲染,我们首先需要将这些值存储在组件状态中。这样,当它们更改时,就会触发渲染。可以使用当前的 innerWidth和innerHeight初始化它们,如下所示:
const [width, setWidth] = React.useState(window.innerWidth);
const [height, setHeight] = React.useState(window.innerHeight);
return (
<div>
<div>{`Window width = ${width}`}</div>
<div>{`Window height = ${height}`}</div>
</div>);
剩下要做的就是在调整窗口大小时更新状态。我们需要一个函数来执行更新:
const updateWidthAndHeight = () => {
setWidth(window.innerWidth);
setHeight(window.innerHeight);
};
要监听 resize 事件,我们需要添加一个事件监听器,该监听器在Effect 钩子中完成。在下面的代码中,useEffect调用时没有第二个参数,因此每次渲染组件时它都会运行。它为resize事件添加了一个事件监听器,该事件调用函数来更新组件状态。当不再需要事件监听器时,也必须将其删除,这可以通过使用 effect 钩子的返回值来完成。这将在卸载组件时执行,并且在再次执行效果之前执行,效果会调用window.removeEventListener进行清理:
React.useEffect(() => {
window.addEventListener("resize", updateWidthAndHeight);
return () => window.removeEventListener("resize", updateWidthAndHeight);
});
现在,当此组件位于页面上时,每当浏览器窗口大小调整时,它都会更新宽度和高度的显示。
该组件的完整代码可以在这里找到。
缩放画布
处理调整大小事件的更“真实”场景是在画布上绘图时。随着显示大小的变化,画布的比例很可能需要改变。我们现在将构建一个组件,它将渲染画布,在其上绘制一些形状,并在浏览器调整大小时以相应的比例重新绘制这些形状。
首先,我们需要一个以画布、比例作为参数并在其上绘制一些内容的函数:
function draw(canvas, scaleX, scaleY) {
const context = canvas.getContext("2d");
context.scale(scaleX, scaleY);
context.clearRect(0, 0, canvas.clientWidth, canvas.clientHeight);
context.beginPath();
context.setLineDash([]);
context.lineWidth = 2;
context.strokeStyle = "red";
context.moveTo(0, 100);
context.lineTo(scaleWidth, 100);
context.moveTo(0, 400);
context.lineTo(scaleWidth, 400);
context.stroke();
context.lineWidth = 1;
context.strokeStyle = "blue";
context.fillStyle = "blue";
context.rect(200, 200, 100, 100);
context.fill();
context.closePath();
}
该函数获取一个2D绘图上下文,根据参数缩放,清除,并绘制两条线和一个实心矩形。
我们还需要一个画布元素来绘制。我们需要使用useRef 钩子保留对此画布的引用;这允许在组件代码中的其他地方访问画布元素:
const canvas = React.useRef(null);
return <canvas ref={canvas} style={{ width: "100%", height: "100%" }} />;
ref 初始化为null ,并通过元素上的ref属性将其设置为 canvas 元素。要访问引用的 canvas 元素,可使用canvas.current 。
当画布大小调整时,我们需要一个函数来调用,该函数将画布宽度和高度属性设置为画布的实际宽度和高度,并将设置当前窗口大小的比例。出于本指南的目的,将使用这个函数,该函数使用 500 的宽度和高度作为比例:
const calculateScaleX = () => canvas.current.clientWidth / scaleWidth;
const calculateScaleY = () => canvas.current.clientHeight / scaleHeight;
const resized = () => {
canvas.current.width = canvas.current.clientWidth;
canvas.current.height = canvas.current.clientHeight;
setScale({ x: calculateScaleX(), y: calculateScaleY() });
};
比例需要存储在组件状态中,并将在两个轴上初始化为 1,如下所示:
const [scale, setScale] = React.useState({ x: 1, y: 1 });
每当调整浏览器窗口大小时,我们都需要计算比例并更新存储在组件状态中的值。与前面的示例一样,这是使用没有第二个参数的Effect 钩子来完成的,以添加和删除resize事件的侦听器,这次调用resized函数:
React.useEffect(() => {
const currentCanvas = canvas.current;
currentCanvas.addEventListener("resize", resized);
return () => currentCanvas.removeEventListener("resize", resized);
});
最后,每当比例发生变化时,我们都需要绘制画布。为此,我们可以再次使用Effect 钩子,但这次,我们将为其提供比例状态值的第二个参数。这意味着钩子仅在比例发生变化时执行。在钩子内部,我们只需调用 draw 函数并将画布和比例作为参数传递即可:
React.useEffect(() => {
draw(canvas.current, scale.x, scale.y);
}, [scale]);
该组件现在会更改画布的比例,并在浏览器调整大小时重新绘制它。此组件的代码可在此处找到。
结论
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~