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

JavaScript实现带打字机效果的词语交替切换问题求助

打字机效果循环替换词语的实现问题与解决方案

需求说明

点击id为btn的按钮后,需实现以下流程:

  1. 以打字机效果输出一段固定字符串
  2. 删除最后一个词语,再以打字机效果输出数组中的第一个词语
  3. 等待几秒后删除该词语,继续以打字机效果输出数组下一个词语,循环往复

初始尝试的代码仅能直接替换最后一个词语,无法结合打字机效果完成删除与输入的过渡,以下是具体分析与改进方案。

初始尝试代码

HTML

<button id="btn" type="button">Type</button>
<div id="demo"></div>

JavaScript

var i = 0;
var j = 0;
var txt = "To me, you are extremely cool";
var array = [" pretty", " smart", " beautiful", " gorgeous", " cool"];
var speed = 50;

document.getElementById("btn").onclick = function () {
  typeWriter();
  setInterval(rotate, 5000);
};

function typeWriter() {
  if (i < txt.length) {
    document.getElementById("demo").innerHTML += txt.charAt(i);
    i++;
    setTimeout(typeWriter, speed);
  }
}

function rotate() {
  let demo = document.getElementById("demo");
  let words = demo.innerHTML.split(" ");
  words.pop();
  demo.innerHTML = words.join(" ");
  document.getElementById("demo").innerHTML += array[j];
  j = (j + 1) % array.length;
}

改进后的解决方案

通过async/await控制异步流程,拆分固定文本与可变文本到独立元素,实现了逐字符输入、删除的打字机动画效果:

HTML

<body>
    <button id="btn" type="button">Type</button>
    <div class="display">
        <span class="root"></span>
        <span class="tail"></span>
    </div>
</body>

CSS

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    display: flex;
    justify-content: center;
    align-items: center;
  }
  
.display {
    box-shadow: 0 0 2px 2px pink;
    padding: 1rem;
    border-radius: 5px;
  }

#btn {
    padding: 30px;
    border-radius: 6px;
    left: 50px;
    position: absolute;
    cursor: pointer;
}

JavaScript

document.getElementById("btn").onclick = function () {
  main();
};

function sleep(ms) {
  return new Promise((r) => setTimeout(r, ms));
}

async function typewrite(txt, el) {
  el.innerText = "";
  for (const char of txt) {
    el.textContent += char;
    await sleep(100);
  }
}

async function typewrite2(txt, el) {
  for (const char of txt) {
    el.textContent = el.textContent.slice(0, -1);
    await sleep(250);
  }
}

async function main() {
  const TAILS = ["pretty", "smart", "beautiful", "gorgeous", "cool"];
  const ROOT_TEXT = "I think you are ";
  const root = document.querySelector(".root");
  const tail = document.querySelector(".tail");
  await typewrite(ROOT_TEXT, root);
  let tailIndex = 0;
  while (true) {
    await typewrite(TAILS[tailIndex], tail);
    await sleep(1000);
    await typewrite2(TAILS[tailIndex], tail);
    await sleep(1000);
    tailIndex = (tailIndex + 1) % TAILS.length;
  }
}

关键说明

  1. 初始代码问题:rotate函数直接通过split/pop/join修改DOM内容,没有逐字符删除和输入的过渡逻辑,因此无法呈现打字机效果的替换过程。
  2. 改进方案优势:
    • 将固定文本与可变文本拆分到两个span元素,避免修改固定内容,仅操作可变部分
    • 用async/await配合sleep函数精准控制每个字符的输入/删除间隔,实现流畅的打字机动画
    • 通过while(true)循环实现词语的无限轮播
  3. CSS实现可行性:纯CSS无法完成该需求。CSS动画依赖预定义的关键帧,无法处理动态文本内容的循环切换,也无法实现复杂的流程控制(如等待、逐字符操作的时序逻辑),必须结合JavaScript来实现这类交互式、动态的文本动画。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 09:44:52