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

如何实现Stripe官网模拟真人打字运行代码的代码片段动画?

Stripe滚动触发动态代码效果实现方案

核心实现逻辑

这个效果本质是滚动触发的逐字打字动画+运行态模拟,核心可以拆成三个模块实现:

  • 滚动触发判定:用IntersectionObserver监听代码容器的可见性,当容器进入视口比例达到预设值(比如30%)时才启动动画,既符合滚动展示的交互逻辑,性能也远优于传统的scroll事件监听,还可以避免动画重复执行。
  • 真人输入模拟:提前把要展示的代码拆分为逐行的序列,逐字符插入到代码容器中,每次插入的间隔设为30~80ms的随机值,不要用固定间隔,能最大程度还原真人打字的错落感,再搭配CSS动画实现的闪烁光标,效果更逼真。
  • 运行效果模拟:某一行输入代码打完后,隐藏光标,插入100~1000ms不等的等待时长,也可以加个小点跳动的加载动效,延迟结束后直接输出运行结果(比如返回值、控制台日志等),再恢复光标继续下一行的打字即可。

关键代码示例

HTML结构

<div class="code-card">
  <pre><code class="code-content"></code></pre>
  <span class="typing-cursor"></span>
</div>

核心CSS

.typing-cursor {
  display: inline-block;
  width: 2px;
  height: 1em;
  background: #ffffff;
  margin-left: 3px;
  vertical-align: text-bottom;
  animation: blink 1s step-end infinite;
}
@keyframes blink {
  0%, 100% { opacity: 1; }
  50% { opacity: 0; }
}

JS逻辑

// 提前定义代码序列,type区分是输入代码还是运行输出
const codeList = [
  { type: 'input', content: "import Stripe from 'stripe';" },
  { type: 'input', content: "const stripe = new Stripe('sk_test_xxxxxxxxxx');" },
  { type: 'input', content: "const paymentIntent = await stripe.paymentIntents.create({" },
  { type: 'input', content: "  amount: 1999," },
  { type: 'input', content: "  currency: 'cny'," },
  { type: 'input', content: "  payment_method_types: ['card']" },
  { type: 'input', content: "});" },
  { type: 'output', content: "// ✅ 请求成功,PaymentIntent ID:pi_3KDxxxxxxxxx" }
]

const codeEl = document.querySelector('.code-content')
const cursorEl = document.querySelector('.typing-cursor')

// 逐字打印函数
async function typeSingleLine(text) {
  for (let char of text) {
    codeEl.textContent += char
    // 随机间隔模拟真人打字
    await new Promise(resolve => setTimeout(resolve, Math.random() * 50 + 30))
  }
  codeEl.textContent += '\n'
}

// 启动完整动画
async function runCodeAnimation() {
  for (let item of codeList) {
    if (item.type === 'input') {
      cursorEl.style.display = 'inline-block'
      await typeSingleLine(item.content)
    } else if (item.type === 'output') {
      cursorEl.style.display = 'none'
      // 模拟代码运行等待时间
      await new Promise(resolve => setTimeout(resolve, 800))
      codeEl.textContent += item.content + '\n'
    }
  }
}

// 滚动监听触发动画
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      runCodeAnimation()
      // 触发一次后取消监听,避免重复执行
      observer.unobserve(entry.target)
    }
  })
}, { threshold: 0.3 })

observer.observe(document.querySelector('.code-card'))

可优化方向

  • 可以接入语法高亮库,每打完一行代码就调用一次单行高亮方法,不用等全部代码打完再处理,展示效果更贴近真实编辑器。
  • 如果需要做多语言/多场景的代码标签切换,只需要提前定义多组codeList,点击对应标签时清空容器内容,再执行对应序列的动画即可。
  • 动画执行过程中尽量直接操作textContent,不要频繁插入DOM节点,能减少不必要的重排重绘,提升流畅度。

内容的提问来源于stack exchange,提问作者ROHIT K F

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 06:27:04