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

如何在触屏设备上检测DIV元素被触摸?

触屏设备触摸检测替代鼠标点击实现游戏结束功能

现有一个运行在触屏设备(如手机)上的HTML游戏,原本通过以下代码检测名为W的DIV被点击时触发gameOver()结束游戏:

W.onmousedown = function () {
  gameOver();
}

现在需要替换为检测用户触摸该DIV的操作,且已知click事件无法触发游戏结束,以下是完整代码:

完整原代码

HTML

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Play WASD online</title>
  <link href="style.css" rel="stylesheet" type="text/css" />
</head>

<body>
  <noscript>turn on javascript to play this game or noob :P</noscript>
  <p id="RandomLetters" class="RandomLetters">
  </p>
  <p id="Timer" class="Timer">
  </p>
  <br>
  <p id="Lives" class="Lives">
  </p>
  <p id="Score" class="Score">
  </p>
  <div class="center">
    <div id="W" class="W">
    </div>
  </div>
  <div class="center2">
    <div id="A" class="A">
    </div>
    <div id="S" class="S">
    </div>
    <div id="D" class="D">
    </div>
  </div>
  <script src="script.js"></script>
</body>

</html>

CSS

body {
  background-color: black;
}

p {
  font-family: Verdana;
  color: white;
  font-size: 20px;
}

.RandomLetters {
  float: left;
}

.Timer {
  float: right;
}

.Lives {
  position: absolute;
  left: auto;
}

.Score {
  position: absolute;
  right: 0;
}

.center {
  display: flex;
  justify-content: center;
  align-items: center;
  position: absolute;
  top: 0;
  bottom: 100px;
  left: 0;
  right: 0;
  margin: auto;
}

.center2 {
  display: flex;
  justify-content: center;
  align-items: center;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  margin: auto;
}

.W,
.A,
.S,
.D {
  height: 50px;
  width: 50px;
  font-family: Verdana;
  text-align: center;
}

JavaScript

var gameIsPlaying = true;

function game() {
  gameIsPlaying = true;
  const RandomLetterGUI = document.getElementById("RandomLetters")
  const TimerGUI = document.getElementById("Timer")
  const LivesGUI = document.getElementById("Lives")
  const ScoreGUI = document.getElementById("Score")
  const W = document.getElementById("W")
  const A = document.getElementById("A")
  const S = document.getElementById("S")
  const D = document.getElementById("D")
  W.style.backgroundColor = "white";
  W.innerHTML = 'W'
  A.style.backgroundColor = "white";
  A.innerHTML = 'A'
  S.style.backgroundColor = "white";
  S.innerHTML = 'S'
  D.style.backgroundColor = "white";
  D.innerHTML = 'D'
  const letters = [
    "W",
    "A",
    "S",
    "D"
  ]
  var seconds = 60;
  var lives = 3;
  var score = 0;
  var timerId = setInterval(countdown, 1000);

  function countdown() {
    if (seconds == -1) {
      gameOver()
    } else {
      if (seconds > 9) {
        TimerGUI.innerHTML = ':' + seconds;
      } else {
        TimerGUI.innerHTML = ':0' + seconds;
      }
      seconds--;
    }
  }
  countdown()
  const updateLives = setInterval(displayLives, 0)
  const ScoreUpdate = setInterval(updateScore, 0)

  function gameOver() {
    gameIsPlaying = false
    clearTimeout(timerId)
    clearTimeout(updateLives)
    clearTimeout(ScoreUpdate)
    W.style.backgroundColor = "red";
    W.innerHTML = ''
    A.style.backgroundColor = "red";
    A.innerHTML = ''
    S.style.backgroundColor = "red";
    S.innerHTML = ''
    D.style.backgroundColor = "red";
    D.innerHTML = ''
    RandomLetterGUI.innerHTML = ''
    TimerGUI.innerHTML = ''
    LivesGUI.innerHTML = ''
    ScoreGUI.innerHTML = ''
  }

  function updateScore() {
    ScoreGUI.innerHTML = "Score: " + score
  }

  function displayLives() {
    LivesGUI.innerHTML = "Remaining Lives: " + lives
    if (lives == 0) {
      gameOver()
    }
  }

  function letter() {
    var item = letters[Math.floor(Math.random() * letters.length)];
    RandomLetterGUI.innerHTML = "Next Letter: " + item
    var pickedLetterTime = Math.floor(Date.now() / 1000)
    document.onkeypress = function(e) {
      if (gameIsPlaying) {
        var key = e.key
        if (key.toUpperCase() != item) {
          lives -= 1;
          if (score >= 0) {
            score -= 50;
          }
        } else {
          var pressedKeyTime = Math.floor(Date.now() / 1000)
          var seconds = pressedKeyTime - pickedLetterTime
          if (seconds > 0 && seconds < 1.5) {
            score += 500
          }
          if (seconds >= 1.5 && seconds < 3) {
            score += 350
          }
          if (seconds >= 3 && seconds < 5) {
            score += 150
          }
        }
      }
    };
    document.onkeydown = function(e) {
      var key = e.key
      if (key == "w") {
        W.style.backgroundColor = "lime";
        W.innerHTML = ''
      }
      if (key == "a") {
        A.style.backgroundColor = "lime";
        A.innerHTML = ''
      }
      if (key == "s") {
        S.style.backgroundColor = "lime";
        S.innerHTML = ''
      }
      if (key == "d") {
        D.style.backgroundColor = "lime";
        D.innerHTML = ''
      }
    }
    document.onkeyup = function(e) {
      if (e.key == "w") {
        W.style.backgroundColor = "white";
        W.innerHTML = 'W'
      }
      if (e.key == "a") {
        A.style.backgroundColor = "white";
        A.innerHTML = 'A'
      }
      if (e.key == "s") {
        S.style.backgroundColor = "white";
        S.innerHTML = 'S'
      }
      if (e.key == "d") {
        D.style.backgroundColor = "white";
        D.innerHTML = 'D'
      }
    }
    // touchscreen compatibility
    W.onclick = function() {
      gameOver();
    }
  }
  letter()
}
game()

function resetGame() {
  if (gameIsPlaying == false) {
    document.onkeypress = function(e) {
      var key = e.key
      if (key == "Enter") {
        game()
      }
    }
  }
}
setInterval(resetGame, 0)

解决方案

触屏设备上要替代mousedown,直接用原生的touchstart触摸事件即可,这比click更可靠,不会有延迟或触发失败的问题。

核心修改

找到JS代码中// touchscreen compatibility注释下的W.onclick代码,替换成以下内容:

// touchscreen compatibility
function triggerGameOver(e) {
  // 针对触摸事件阻止默认行为,避免触发浏览器滚动、缩放等操作
  if (e.type === 'touchstart') {
    e.preventDefault();
  }
  gameOver();
}
// 保留鼠标点击支持
W.onmousedown = triggerGameOver;
// 添加触摸支持
W.addEventListener('touchstart', triggerGameOver);

拓展:让A/S/D也支持触屏操作

如果需要让A、S、D三个按键也能通过触摸模拟键盘按下/抬起的效果,可以给它们添加touchstart和touchend事件:

// A键触摸事件
A.addEventListener('touchstart', function(e) {
  e.preventDefault();
  A.style.backgroundColor = "lime";
  A.innerHTML = '';
});
A.addEventListener('touchend', function(e) {
  e.preventDefault();
  A.style.backgroundColor = "white";
  A.innerHTML = 'A';
});

// S键触摸事件
S.addEventListener('touchstart', function(e) {
  e.preventDefault();
  S.style.backgroundColor = "lime";
  S.innerHTML = '';
});
S.addEventListener('touchend', function(e) {
  e.preventDefault();
  S.style.backgroundColor = "white";
  S.innerHTML = 'S';
});

// D键触摸事件
D.addEventListener('touchstart', function(e) {
  e.preventDefault();
  D.style.backgroundColor = "lime";
  D.innerHTML = '';
});
D.addEventListener('touchend', function(e) {
  e.preventDefault();
  D.style.backgroundColor = "white";
  D.innerHTML = 'D';
});

为什么click事件没用?

触屏设备上click事件有300ms的延迟,而且如果页面存在滚动、缩放或者元素有其他触摸交互时,浏览器可能不会触发click事件。而touchstart是触摸开始时立即触发的原生事件,完全适配触屏场景,不会有这些问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 05:00:54