← 返回

Timeline 演示效果分析与实现

8/25/2025

本文分析了 Josh Comeau 在 useDeferredValue 文章中展示的交互式 timeline 演示效果,并尝试复现其核心实现。

演示效果概述

Josh Comeau 的文章中有一个非常精彩的交互式 timeline 演示,用来可视化 React 渲染过程:

  1. 时间轴展示:水平时间轴显示渲染过程的时间进度(0-150ms)
  2. 渲染块可视化:不同颜色的块表示不同组件的渲染时间
  3. 交互式回放:可以点击按钮触发渲染,并实时观察过程
  4. 悬停详情:鼠标悬停在渲染块上显示详细信息

技术分析

核心组件结构

根据页面分析,timeline 演示主要包含以下几个部分:

  1. TimelineContainer: 整个演示的容器
  2. Timeline: 时间轴本体,包含刻度和标签
  3. RenderBlock: 表示单个渲染任务的矩形块
  4. PlayButton: 触发演示的播放按钮
  5. 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 属性
  • 避免不必要的重绘
  • 合理使用 useMemouseCallback

总结

Josh Comeau 的 timeline 演示是一个精心设计的教学工具,它通过可视化的方式帮助开发者理解 React 的渲染过程。其实现涉及多个技术层面:

  1. SVG/Canvas 绘图:用于绘制时间轴和刻度
  2. CSS 动画:实现渲染块的出现效果
  3. JavaScript 动画循环:控制整体播放进度
  4. React 状态管理:管理复杂的演示状态
  5. 响应式设计:确保在各种设备上都能正常工作

这种交互式的演示方式大大提升了技术文章的教学效果,值得我们在自己的技术写作中学习和借鉴。


本文是对优秀技术演示的分析和学习,希望能为大家的技术写作和演示制作提供一些启发。