15.7【TS中级项目】打字速度监测器

发布于:2025-06-21 ⋅ 阅读:(18) ⋅ 点赞:(0)

开发一个应用程序,通过显示随机文本段落并记录用户输入所花费的时间,来测量用户的打字速度。

  • 实现计时器和事件监听器来跟踪打字速度;
  • 使用 TypeScript 处理用户输入并计算结果;
  • 显示结果并向用户提供反馈。

打字速度一直是评估工程师的重要测试之一,因为更快的打字技能意味着更高效的编码。为了测试这个速度,我们将构建一个打字速度检测器。

我们将要创建的内容如下:

  • 一个用于输入文本的输入框;
  • 一个用于显示时间的时间元素;
  • 一个用于显示每分钟字数(WPM)的元素;
  • 一个用于开始测试的“开始”按钮。

HTML 与 CSS

这是一个打字速度测试 Web 应用,用户可以通过它测量自己的打字速度(以每分钟字数 WPM 为单位)。该应用包含以下主要元素:

  • 一个计时器,用于显示剩余时间或计时时长;
  • 一个输入区域,供用户输入测试文本;
  • 一个“开始”按钮,用于启动打字测试。
<html>
  <head>
    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
      body {
        font-family: Arial, sans-serif;
        background: #f4f4f4;
        display: flex;
        justify-content: center;
        align-items: center;
        height: 100vh;
        flex-direction: column;
      }
      .box {
        text-align: center;
        background: #fff;
        padding: 20px;
        border-radius: 10px;
        box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
        width: 400px;
      }
      h1 {
        font-size: 24px;
        margin-bottom: 20px;
      }
      #txt {
        font-size: 18px;
        margin-bottom: 20px;
        font-weight: bold;
      }
      #inp {
        width: 100%;
        height: 100px;
        font-size: 16px;
        padding: 10px;
        margin-bottom: 20px;
        border: 1px solid #ccc;
        border-radius: 5px;
        resize: none;
      }
      .stats {
        display: flex;
        justify-content: space-between;
        margin-top: 20px;
      }
      button {
        padding: 10px 20px;
        background: #4CAF50;
        color: white;
        border: none;
        border-radius: 5px;
        cursor: pointer;
      }
      button:disabled {
        background: #ccc;
      }
      button:hover {
        background: #45a049;
      }
    </style>
  </head>
  <body>
    <div class="box">
      <h1>Typing Speed Test</h1>
      <p id="txt">Press Start to begin typing</p>
      <textarea id="inp" placeholder="Start typing here..." disabled></textarea>
      <div class="stats">
        <p id="tm">Time: 0s</p>
        <p id="wpm">WPM: 0</p>
        <button id="start">Start</button>
      </div>
    </div>
    <script defer src="typing.js"></script>
  </body>
</html>

在这个示例中:

  • .box 容器居中显示,设计简洁,包含一个标题、句子显示区、文本输入框和统计信息区。
  • #inp 是一个 textarea,初始状态为禁用(disabled),用户点击 “开始” 按钮(#start)后才会激活输入。
  • #tm(时间)和 #wpm(每分钟字数)会随着用户输入实时更新,用于跟踪用户的打字速度。

TypeScript 逻辑

这段代码创建了一个动态网格,允许用户通过更改网格大小和颜色在上面绘画。它支持通过鼠标事件进行绘画和重置网格的交互操作。

const c = document.querySelector<HTMLDivElement>(".container");
const s = document.querySelector<HTMLInputElement>('.size');
const col = document.querySelector<HTMLInputElement>('.color');
const rBtn = document.querySelector<HTMLButtonElement>('.button');

if (!c || !s || !col || !rBtn) {
  throw new Error("Missing required DOM elements");
}

let sz: number = parseInt(s.value);
let d: boolean = false;

function g(): void {
  c.style.setProperty("--size", sz.toString());
  c.innerHTML = "";

  for (let i = 0; i < sz * sz; i++) {
    const b = document.createElement("div");
    b.classList.add("box");
    b.addEventListener('mouseenter', () => o(b));
    b.addEventListener('mousedown', () => m(b));
    c.appendChild(b);
  }
}

function o(b: HTMLDivElement): void {
  if (!d) return;
  b.style.backgroundColor = col.value;
}

function m(b: HTMLDivElement): void {
  b.style.backgroundColor = col.value;
}

window.addEventListener('mousedown', () => {
  d = true;
});

window.addEventListener('mouseup', () => {
  d = false;
});

function r(): void {
  g();
}

rBtn.addEventListener('click', r);

s.addEventListener('change', () => {
  sz = parseInt(s.value);
  r();
});

g();

在这个示例中:

  • 函数 g() 生成一个大小为 sz × sz 的网格,先清除之前的网格再添加新的单元格。
  • 网格大小根据用户输入(.size 输入框)动态更新。
  • 当鼠标悬停(mouseenter)或点击(mousedown)单元格时,单元格颜色会变成用户选择的颜色(col.value)。
  • 布尔变量 d 用来追踪鼠标是否按下,从而实现流畅绘画效果。
  • 点击重置按钮(.button)会清空并重新创建网格,确保用户无需刷新页面即可重新开始。
  • 当用户更改 .size 输入时,事件监听器 s.addEventListener('change', ...) 会触发网格的更新。

将 TypeScript 文件转换为 JavaScript 文件

现在你需要将 TypeScript 文件转换为浏览器可以执行的 JavaScript 文件。你可以使用以下命令之一来完成转换。

npx  tsc typing.ts
tsc typing.ts
  • 命令 typing.ts 会将 typing.ts 这个 TypeScript 文件编译成 typing.js JavaScript 文件。
  • 默认情况下,输出文件会放在与输入文件相同的目录下。

完整代码

<html>
  <head>
    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
      body {
        font-family: Arial, sans-serif;
        background: #f4f4f4;
        display: flex;
        justify-content: center;
        align-items: center;
        height: 100vh;
        flex-direction: column;
      }
      .box {
        text-align: center;
        background: #fff;
        padding: 20px;
        border-radius: 10px;
        box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
        width: 400px;
      }
      h1 {
        font-size: 24px;
        margin-bottom: 20px;
      }
      #txt {
        font-size: 18px;
        margin-bottom: 20px;
        font-weight: bold;
      }
      #inp {
        width: 100%;
        height: 100px;
        font-size: 16px;
        padding: 10px;
        margin-bottom: 20px;
        border: 1px solid #ccc;
        border-radius: 5px;
        resize: none;
      }
      .stats {
        display: flex;
        justify-content: space-between;
        margin-top: 20px;
      }
      button {
        padding: 10px 20px;
        background: #4CAF50;
        color: white;
        border: none;
        border-radius: 5px;
        cursor: pointer;
      }
      button:disabled {
        background: #ccc;
      }
      button:hover {
        background: #45a049;
      }
    </style>
  </head>
  <body>
    <div class="box">
      <h1>Typing Speed Test</h1>
      <p id="txt">Press Start to begin typing</p>
      <textarea id="inp" placeholder="Start typing here..." disabled></textarea>
      <div class="stats">
        <p id="tm">Time: 0s</p>
        <p id="wpm">WPM: 0</p>
        <button id="start">Start</button>
      </div>
    </div>
    <script defer>
      const txt = document.getElementById("txt");
      const inp = document.getElementById("inp");
      const tm = document.getElementById("tm");
      const wpm = document.getElementById("wpm");
      const startBtn = document.getElementById("start");
      let time = 0;
      let timer = null;
      let isRunning = false;
      const sampleText = "The quick brown fox jumps over the lazy dog"; // Sample sentence

      function startTest() {
        clearInterval(timer);
        isRunning = true;
        time = 0;
        tm.textContent = "Time: 0s";
        wpm.textContent = "WPM: 0";
        inp.value = "";
        inp.disabled = false;
        inp.focus();
        txt.textContent = sampleText;
        timer = setInterval(() => {
          time++;
          tm.textContent = `Time: ${time}s`;
          calculateWPM();
        }, 1000);
      }

      function calculateWPM() {
        let wordsTyped = inp.value.trim().split(/\s+/).length;
          let wordsPerMinute = time > 0 ? Math.round((wordsTyped / time) * 60) : 0;
            wpm.textContent = `WPM: ${wordsPerMinute}`;
        }

        inp.addEventListener("input", () => {
            calculateWPM();

            if (inp.value.toLowerCase().replace(/\s+/g, " ")
                .trim() === sampleText.toLowerCase().replace(/\s+/g, " ").trim()) {
                clearInterval(timer);
                isRunning = false;
                inp.disabled = true;
                wpm.textContent = `WPM: ${Math.round((sampleText.split(" ")
                    .length / time) * 60)}`; 
                alert(`Test Completed! Your WPM: ${wpm.textContent.split(" ")[1]}`);
            }
        });

        startBtn.addEventListener("click", startTest);
    </script>
</body>
</html>

网站公告

今日签到

点亮在社区的每一天
去签到