You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现带进度动画的垂直时间轴:线条绘制时同步切换节点状态

垂直时间轴动画实现思路

核心逻辑拆分

  • 把整体动画拆成两个独立控制的单元:竖线进度绘制动画、节点状态切换动画
  • 提前预处理所有条目数据:统计所有status=true的条目总高度,作为整个进度动画的总长度基准

竖线绘制动画实现

  • 优先用CSS实现更流畅:给进度竖线设置初始height: 0,或者用clip-path: inset(100% 0 0 0)做顶部裁剪,动画触发时将属性更新为总高度/clip-path: inset(0 0 0 0),搭配线性缓动和固定时长即可实现从上到下逐步绘制的效果
  • 如果是节点间分段的独立竖线,可以给每段status=true的竖线按顺序设置递增的动画延迟,前一段播放完成后再启动下一段,更符合逐段推进的视觉效果

节点状态切换实现

  • 先计算每个已完成节点距离时间轴顶部的偏移量,除以总进度长度得到该节点对应的进度百分比
  • 状态切换触发可以选两种方案:
    1. 用requestAnimationFrame实时监听进度动画的当前进度,进度超过对应节点百分比时触发样式切换
    2. 按节点进度百分比计算对应延迟时间,用setTimeout触发,刚好和竖线走到节点的时间对齐
  • 对勾样式切换用CSS transform实现即可:初始对勾设置scale(0)+opacity(0),触发时改为scale(1)+opacity(1),搭配短时长的弹性缓动,视觉效果更自然

核心代码参考

可直接在现有代码基础上调整:

/* 进度竖线基础样式 */
.timeline-progress {
  position: absolute;
  left: 12px;
  top: 0;
  width: 4px;
  background: #1677ff;
  height: 0;
  transition: height 3s linear;
}
/* 已完成节点样式 */
.timeline-item.done .node-circle {
  background: #1677ff;
  border-color: #1677ff;
}
.timeline-item .check-icon {
  transform: scale(0);
  opacity: 0;
  transition: all 0.2s ease-out 0.05s;
}
.timeline-item.done .check-icon {
  transform: scale(1);
  opacity: 1;
}
// 动画启动逻辑
const runTimelineAnimation = () => {
  // 动态计算总进度高度
  const doneItemList = Array.from(document.querySelectorAll('.timeline-item[status="true"]'))
  const totalProgressHeight = doneItemList.at(-1).offsetTop
  // 启动竖线绘制动画
  document.querySelector('.timeline-progress').style.height = `${totalProgressHeight}px`
  // 批量设置节点状态切换延迟
  doneItemList.forEach(item => {
    const delayTime = (item.offsetTop / totalProgressHeight) * 3000 // 3000对应CSS中3s总动画时长
    setTimeout(() => item.classList.add('done'), delayTime)
  })
}

优化提示

  • 如果条目高度不固定,用getBoundingClientRect()动态计算节点位置,不要写死高度值
  • 动画总时长可根据需求自由调整,节点切换的微小弹性动画能大幅提升交互质感
  • 无需引入第三方动画库,原生CSS+JS即可实现全部效果,性能也更优

内容的提问来源于stack exchange,提问作者dev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 00:06:07