如何用ReactJS和TailwindCSS实现斜向曲线响应式时间线?
实现从左下角到右上角的曲线时间线(React + Tailwind CSS)
核心思路
利用SVG绘制可缩放的贝塞尔曲线作为时间线主体,通过JavaScript计算曲线上的坐标点定位时间节点,结合Tailwind CSS实现响应式布局与样式优化。
完整代码实现
import React, { useRef, useState, useEffect } from 'react'; const CurvedTimeline = () => { const pathRef = useRef(null); const [itemPositions, setItemPositions] = useState([]); // 时间线节点数据 const timelineItems = [ { id: 1, title: "项目启动", content: "确定项目需求与核心目标" }, { id: 2, title: "原型设计", content: "完成产品交互原型与视觉设计" }, { id: 3, title: "开发阶段", content: "核心功能开发与内部测试" }, { id: 4, title: "Beta发布", content: "面向测试用户开放体验" }, { id: 5, title: "正式上线", content: "产品全量发布并持续迭代" }, ]; // 计算节点在曲线上的位置 const calculatePositions = () => { if (!pathRef.current) return; const path = pathRef.current; const totalLength = path.getTotalLength(); const positions = timelineItems.map((_, index) => { // 均匀分布节点,首尾预留空间避免堆积 const fraction = (index + 1) / (timelineItems.length + 1); const point = path.getPointAtLength(totalLength * fraction); return { x: point.x, y: point.y }; }); setItemPositions(positions); }; // 初始化与窗口 resize 时重新计算位置 useEffect(() => { calculatePositions(); window.addEventListener('resize', calculatePositions); return () => window.removeEventListener('resize', calculatePositions); }, [timelineItems.length]); return ( <div className="relative min-h-screen w-full p-4 md:p-8"> {/* SVG 曲线时间线 */} <svg ref={pathRef} className="absolute inset-0 w-full h-full pointer-events-none"> <path d="M 2% 98% C 25% 75%, 75% 25%, 98% 2%" stroke="#3b82f6" strokeWidth="3" fill="none" strokeLinecap="round" /> </svg> {/* 时间线节点 */} {timelineItems.map((item, index) => ( <div key={item.id} className="absolute bg-white rounded-lg shadow-lg p-4 max-w-xs md:max-w-sm transition-all hover:shadow-xl" style={ itemPositions[index] ? { left: `${itemPositions[index].x}px`, top: `${itemPositions[index].y}px`, transform: 'translate(-50%, -50%)', } : {} } > <div className="w-6 h-6 rounded-full bg-blue-500 mb-2 mx-auto"></div> <h3 className="font-bold text-lg text-gray-800">{item.title}</h3> <p className="text-gray-600 mt-1">{item.content}</p> </div> ))} </div> ); }; export default CurvedTimeline;
关键细节说明
SVG曲线设计
- 使用三次贝塞尔曲线(
C指令),坐标采用百分比单位,确保曲线随容器自适应缩放 M 2% 98%定义起点(左下角),C 25% 75%, 75% 25%, 98% 2%定义两个控制点和终点(右上角),调整控制点可灵活改变曲线弧度
- 使用三次贝塞尔曲线(
节点定位逻辑
- 通过
path.getTotalLength()获取曲线总长度,path.getPointAtLength()获取指定长度处的坐标 - 按
(index+1)/(总节点数+1)的比例均匀分配节点,避免节点堆积在曲线两端
- 通过
响应式处理
- 监听窗口
resize事件,重新计算节点位置,确保始终贴合曲线 - Tailwind的
max-w-xs/max-w-sm等类实现节点在不同屏幕尺寸下的自适应宽度
- 监听窗口
样式优化
- 节点使用
translate(-50%, -50%)实现基于曲线点的居中定位 - 添加
pointer-events-none到SVG,避免遮挡节点的交互事件 - hover阴影效果提升交互体验
- 节点使用
扩展优化建议
- 防抖处理:为resize事件添加防抖函数,减少频繁计算带来的性能消耗
- 自定义曲线:允许通过props传递曲线的控制点参数,实现不同形状的时间线
- 节点连接:为每个节点添加指向曲线的箭头或连线,增强视觉关联
- 动画效果:添加节点进入动画或滚动触发的显示效果
内容的提问来源于stack exchange,提问作者gggg
相关产品推荐
相关产品推荐

