如何在React Konva中实现适配矩形的文本无限滚动?
在React Konva中实现仅指定矩形内的Marquee滚动效果
核心方案
通过Konva的裁剪功能将矩形区域设为可视范围,配合Tween动画控制文本滚动路径,超出矩形的部分自动隐藏,同时修复原代码的内存泄漏问题。
修改后的完整代码
import { useEffect, useRef, useMemo } from "react"; import Konva, { Easings } from "konva"; import { Rect, Text, Group } from "react-konva"; import { useTextWidth } from "@tag0/use-text-width"; export const InfiniteloopFUN = (props) => { const textinfoRef = useRef(null); const tweenRef = useRef(null); const txt = "continuous infinite text loop"; // 抽离矩形参数,方便统一维护 const rectConfig = useMemo(() => ({ x: 200, y: 46, width: 100, height: 20 }), []); // 缓存文本宽度,避免重复计算 const txtwidth = useTextWidth({ text: txt, font: "20px sans-serif" }); // 动画结束位置:矩形左边界减去文本宽度,确保文本完全滚出可视区域 const xposfin = rectConfig.x - txtwidth; useEffect(() => { if (!textinfoRef.current) return; // 创建Tween动画并存储到ref tweenRef.current = new Konva.Tween({ node: textinfoRef.current, easing: Easings.Linear, duration: 5, x: xposfin, // 动画结束自动重置播放,替代setInterval更可靠 onFinish: () => { tweenRef.current.reset(); tweenRef.current.play(); } }); // 启动动画 tweenRef.current.play(); // 清理副作用,避免内存泄漏 return () => { if (tweenRef.current) { tweenRef.current.stop(); tweenRef.current.destroy(); } }; }, [xposfin]); return ( <Group> {/* 可视区域的背景矩形 */} <Rect {...rectConfig} fill="black" /> {/* 裁剪容器:仅显示矩形范围内的内容 */} <Group clipX={rectConfig.x} clipY={rectConfig.y} clipWidth={rectConfig.width} clipHeight={rectConfig.height} > {/* 文本起始位置:矩形右边界,刚好从右侧进入可视区域 */} <Text x={rectConfig.x + rectConfig.width} y={rectConfig.y} fill="orange" fontSize={20} text={txt} ref={textinfoRef} /> </Group> </Group> ); };
关键改动说明
- 添加裁剪容器:利用
Group的clipX/clipY/clipWidth/clipHeight属性,将裁剪区域与目标矩形完全对齐,自动隐藏超出矩形的文本内容。 - 优化动画逻辑:用Tween的
onFinish回调替代setInterval,避免定时器与动画时长不匹配的问题,更贴合Konva的动画生命周期。 - 修复内存泄漏:在组件卸载时停止并销毁Tween实例,清除残留的动画资源。
- 参数缓存与抽离:将矩形参数和文本宽度用
useMemo缓存,减少不必要的重计算和重渲染。 - 可选无缝滚动优化:如果文本宽度小于矩形宽度,可将文本拼接为
txt + " " + txt,实现无空白间隙的无缝循环滚动。
内容的提问来源于stack exchange,提问作者Tarquos
相关产品推荐
相关产品推荐

