如何使用CSS和JavaScript在React容器内将单个字符随机定位排布
实现方案
你只需要修改3个核心逻辑即可实现字符随机散列效果:
- 给外层容器设置相对定位,每个字符元素设置绝对定位,确保位置是基于容器计算
- 为每个单独的字符生成专属的随机坐标,不要全局仅生成一组随机值
- 修复useEffect的空依赖问题,避免窗口resize事件重复绑定
样式文件(styles.css)
* { margin: 0; padding: 0; box-sizing: border-box; } .container { position: relative; width: 100vw; height: 100vh; overflow: hidden; } .char-item { position: absolute; transition: all 0.4s ease; user-select: none; }
修改后的组件代码
import React, { useState, useEffect } from "react"; import "./styles.css"; // 拆分文本组件,新增containerSize参数接收容器宽高 const SplitText = React.memo(({ str, containerSize }) => { return ( <div> {str.split("").map((item, index) => { // 每个字符单独生成随机位置,减去20是预留字符尺寸避免超出容器 const randLeft = Math.floor(Math.random() * (containerSize.width - 20)); const randTop = Math.floor(Math.random() * (containerSize.height - 20)); return ( <div key={index} className="char-item" style={{ left: `${randLeft}px`, top: `${randTop}px` }} > {item} </div> ); })} </div> ); }); function debounce(fn, ms) { let timer; return (_) => { clearTimeout(timer); timer = setTimeout((_) => { timer = null; fn.apply(this, arguments); }, ms); }; } export default function App() { const [dimensions, setDimensions] = useState({ height: window.innerHeight, width: window.innerWidth }); useEffect(() => { const debouncedHandleResize = debounce(function handleResize() { setDimensions({ height: window.innerHeight, width: window.innerWidth }); }, 1000); window.addEventListener("resize", debouncedHandleResize); return () => { window.removeEventListener("resize", debouncedHandleResize); }; }, []); // 新增空依赖,仅组件挂载时绑定一次事件 return ( <div className="container"> <SplitText str={"Lucie Bachman"} containerSize={dimensions} /> <SplitText str={"Hey, this is my first post on StackOverflow!"} containerSize={dimensions} /> </div> ); }
可选优化
如果需要实现字符归位、hover交互等效果,可以额外新增状态控制字符的position值,切换随机坐标和正常文本流的位置即可。如果要避免字符部分超出容器,可以通过useRef获取每个字符的实际宽高后再计算随机坐标。
内容的提问来源于stack exchange,提问作者Bhushan
相关产品推荐
相关产品推荐

