← 返回
Timeline 演示效果分析与实现
8/25/2025
本文分析了 Josh Comeau 在 useDeferredValue 文章中展示的交互式 timeline 演示效果,并尝试复现其核心实现。
演示效果概述
Josh Comeau 的文章中有一个非常精彩的交互式 timeline 演示,用来可视化 React 渲染过程:
- 时间轴展示:水平时间轴显示渲染过程的时间进度(0-150ms)
- 渲染块可视化:不同颜色的块表示不同组件的渲染时间
- 交互式回放:可以点击按钮触发渲染,并实时观察过程
- 悬停详情:鼠标悬停在渲染块上显示详细信息
技术分析
核心组件结构
根据页面分析,timeline 演示主要包含以下几个部分:
- TimelineContainer: 整个演示的容器
- Timeline: 时间轴本体,包含刻度和标签
- RenderBlock: 表示单个渲染任务的矩形块
- PlayButton: 触发演示的播放按钮
- StateDisplay: 显示当前状态值的区域
实现原理猜测
useDeferredValue:视频 + 时间轴(单次点击)
0ms
0ms
0ms
0ms
0ms
1ms
1ms
1ms
1ms
1ms
1ms
count 1 | dCount 0
count0
deferredCount0
同步:已更新
0ms / 1ms
关键技术点
1. 时间轴的实现
时间轴使用 SVG 或 Canvas 实现,主要包含:
- 水平基线
- 时间刻度标记(10ms, 20ms, 30ms…)
- 刻度标签
const Timeline = ({ duration = 150, segments = 15 }) => {
const segmentWidth = 100 / segments; // 百分比宽度
return (
<div className="timeline">
<div className="timeline-track">
{Array.from({ length: segments + 1 }, (_, i) => (
<div
key={i}
className="timeline-tick"
style={{ left: `${i * segmentWidth}%` }}
>
<span>{i * 10}ms</span>
</div>
))}
</div>
</div>
);
};
2. 渲染块动画
渲染块的出现使用了精心设计的动画:
- 从左到右的进度条效果
- 不同组件用不同颜色区分
- 支持暂停、中断等状态
const RenderBlock = ({
startTime,
duration,
component,
color,
isActive
}) => {
const startPercent = (startTime / 150) * 100;
const widthPercent = (duration / 150) * 100;
return (
<div
className={`render-block ${isActive ? 'active' : ''}`}
style={{
left: `${startPercent}%`,
width: `${widthPercent}%`,
backgroundColor: color,
animationDuration: `${duration}ms`
}}
>
{component}
</div>
);
};
3. 状态管理
演示需要管理复杂的状态:
- 当前播放时间
- 渲染任务队列
- 组件状态值
- 播放/暂停状态
const useTimelineState = () => {
const [currentTime, setCurrentTime] = useState(0);
const [isPlaying, setIsPlaying] = useState(false);
const [renderTasks, setRenderTasks] = useState([]);
const [componentStates, setComponentStates] = useState({
count: 0,
deferredCount: 0
});
const playAnimation = useCallback(() => {
setIsPlaying(true);
// 启动动画循环
}, []);
return {
currentTime,
isPlaying,
renderTasks,
componentStates,
playAnimation
};
};
4. 动画循环
使用 requestAnimationFrame
实现流畅的动画:
useEffect(() => {
if (!isPlaying) return;
let animationId;
const startTime = Date.now();
const animate = () => {
const elapsed = Date.now() - startTime;
setCurrentTime(elapsed);
if (elapsed < totalDuration) {
animationId = requestAnimationFrame(animate);
} else {
setIsPlaying(false);
}
};
animationId = requestAnimationFrame(animate);
return () => {
if (animationId) {
cancelAnimationFrame(animationId);
}
};
}, [isPlaying, totalDuration]);
CSS 样式技巧
渲染块的视觉效果
.render-block {
position: absolute;
height: 40px;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
font-weight: 600;
color: white;
transform: scaleX(0);
transform-origin: left;
transition: transform 0.1s ease-out;
}
.render-block.active {
transform: scaleX(1);
}
.render-block:hover {
filter: brightness(1.1);
z-index: 10;
}
时间轴样式
.timeline {
position: relative;
width: 100%;
height: 60px;
background: var(--ls-secondary-background-color);
border-radius: 8px;
overflow: hidden;
}
.timeline-track {
position: absolute;
bottom: 0;
width: 100%;
height: 20px;
border-top: 1px solid var(--ls-border-color);
}
.timeline-tick {
position: absolute;
height: 100%;
border-left: 1px solid var(--ls-border-color);
}
.timeline-tick span {
position: absolute;
top: 2px;
left: 2px;
font-size: 10px;
color: var(--ls-muted-text-color);
}
技术难点
1. 精确的时间控制
需要精确控制每个渲染块的出现时机和持续时间,确保动画与实际的 React 渲染行为保持一致。
2. 响应式设计
timeline 需要在不同屏幕尺寸下都能正常工作,这需要使用百分比布局和媒体查询。
3. 性能优化
由于涉及频繁的动画更新,需要注意性能优化:
- 使用
will-change
CSS 属性 - 避免不必要的重绘
- 合理使用
useMemo
和useCallback
总结
Josh Comeau 的 timeline 演示是一个精心设计的教学工具,它通过可视化的方式帮助开发者理解 React 的渲染过程。其实现涉及多个技术层面:
- SVG/Canvas 绘图:用于绘制时间轴和刻度
- CSS 动画:实现渲染块的出现效果
- JavaScript 动画循环:控制整体播放进度
- React 状态管理:管理复杂的演示状态
- 响应式设计:确保在各种设备上都能正常工作
这种交互式的演示方式大大提升了技术文章的教学效果,值得我们在自己的技术写作中学习和借鉴。
本文是对优秀技术演示的分析和学习,希望能为大家的技术写作和演示制作提供一些启发。