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

HTML/JavaScript宏录制器播放功能故障排查与修复

宏录制器播放按钮无响应故障修复

我正在使用HTML和JavaScript开发一款宏录制器,其余功能均正常运行,但点击Play(播放)按钮时无响应。调试未发现任何报错,无法定位问题所在,请求协助修复该故障。

当前代码

<!DOCTYPE html>
<html>
<head>
    <title>Macro Recorder</title>
  </head>
  <body>
    <button id="start">Start Recording</button>
    <button id="stop">Stop Recording</button>
    <button id="play">Play Recording</button>
    <button id="save">Save Recording</button>
    <button id="load">Load Recording</button>
    <script>
      var events = [];
      var isRecording = false;

      document.getElementById("start").addEventListener("click", function() {
        isRecording = true;
        events = [];
      });

      document.getElementById("stop").addEventListener("click", function() {
        isRecording = false;
      });

      document.addEventListener("keypress", function(event) {
        if (isRecording) {
          events.push({
            key: event.key,
            charCode: event.charCode
          });
        }
      });

      document.getElementById("play").addEventListener("click", function() {
        events.forEach(function(event) {
          setTimeout(function() {
            var event = new KeyboardEvent("keypress", {
              key: event.key,
              charCode: event.charCode
            });
            document.dispatchEvent(event);
          }, 500);
        });
      });

      document.getElementById("save").addEventListener("click", function() {
        var data = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(events));
        var downloadAnchorNode = document.createElement("a");
        downloadAnchorNode.setAttribute("href", data);
        downloadAnchorNode.setAttribute("download", "events.json");
        document.body.appendChild(downloadAnchorNode);
        downloadAnchorNode.click();
        downloadAnchorNode.remove();
      });

      document.getElementById("load").addEventListener("click", function() {
        var input = document.createElement("input");
        input.setAttribute("type", "file");
        input.addEventListener("change", function() {
          var reader = new FileReader();
          reader.onload = function() {
            events = JSON.parse(reader.result);
          };
          reader.readAsText(input.files[0]);
        });
        input.click();
      });
    </script>
  </body>
</html>

问题分析与修复方案

核心问题

  1. 变量名冲突:播放逻辑里,forEach的参数event和内部创建的KeyboardEvent变量event重名,导致内部无法正确引用录制的事件数据。
  2. 同步触发事件:所有setTimeout都设置为500毫秒后执行,事件会同时触发,而非按录制顺序依次执行。
  3. 事件参数不完整:创建KeyboardEvent时缺少必要参数(如bubbles: true),可能导致事件无法正常冒泡被捕获;且没有指定目标元素,键盘事件需要聚焦元素才能直观体现效果。

修复后的代码

<!DOCTYPE html>
<html>
<head>
    <title>Macro Recorder</title>
  </head>
  <body>
    <!-- 添加输入框用于测试键盘事件效果 -->
    <input type="text" placeholder="点击此处测试录制/播放" id="testInput">
    <button id="start">Start Recording</button>
    <button id="stop">Stop Recording</button>
    <button id="play">Play Recording</button>
    <button id="save">Save Recording</button>
    <button id="load">Load Recording</button>
    <script>
      var events = [];
      var isRecording = false;
      const testInput = document.getElementById('testInput');

      document.getElementById("start").addEventListener("click", function() {
        isRecording = true;
        events = [];
        testInput.focus(); // 录制时自动聚焦输入框
      });

      document.getElementById("stop").addEventListener("click", function() {
        isRecording = false;
      });

      document.addEventListener("keypress", function(event) {
        if (isRecording) {
          events.push({
            key: event.key,
            charCode: event.charCode,
            timestamp: event.timeStamp
          });
        }
      });

      document.getElementById("play").addEventListener("click", function() {
        testInput.focus(); // 播放前聚焦输入框,确保键盘事件生效
        // 用索引计算延迟,实现顺序执行
        events.forEach(function(recordedEvent, index) {
          setTimeout(function() {
            var keyEvent = new KeyboardEvent("keypress", {
              key: recordedEvent.key,
              charCode: recordedEvent.charCode,
              bubbles: true, // 允许事件冒泡
              cancelable: true
            });
            testInput.dispatchEvent(keyEvent); // 直接触发在输入框上,更直观
          }, index * 500); // 按顺序延迟,每个事件间隔500ms
        });
      });

      document.getElementById("save").addEventListener("click", function() {
        var data = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(events));
        var downloadAnchorNode = document.createElement("a");
        downloadAnchorNode.setAttribute("href", data);
        downloadAnchorNode.setAttribute("download", "events.json");
        document.body.appendChild(downloadAnchorNode);
        downloadAnchorNode.click();
        downloadAnchorNode.remove();
      });

      document.getElementById("load").addEventListener("click", function() {
        var input = document.createElement("input");
        input.setAttribute("type", "file");
        input.addEventListener("change", function() {
          var reader = new FileReader();
          reader.onload = function() {
            events = JSON.parse(reader.result);
          };
          reader.readAsText(input.files[0]);
        });
        input.click();
      });
    </script>
  </body>
</html>

修改点说明

  • 重命名forEach的参数为recordedEvent,避免变量冲突。
  • 使用index * 500作为延迟时间,让事件按录制顺序依次触发。
  • 创建KeyboardEvent时添加bubbles: true参数,确保事件能正常传播。
  • 添加测试输入框,播放前自动聚焦,让键盘事件的效果更直观(录制的按键会直接输入到输入框中)。
  • 录制时自动聚焦输入框,提升录制体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 13:20:28