如何在触屏设备上检测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
相关产品推荐
相关产品推荐

