実現したいこと
JavaScriptでゲームを作ろうとしたのですが、タッチイベントが特定の場面で反応しない現象に悩まされています
発生している問題・エラーメッセージ
自分で色々試した結果、「どこかをタッチし、離すと同時に別のところをタッチ」したときに、後に行ったタッチが認識されていないと分かりました。
(後に行ったタッチはtouchstartもmoveもendも発火せず、event.touches.lengthにもカウントされていませんでした)
試したこと
タッチイベントのtargetを変更したり、eventが発火しているタイミングを調べたりしましたが、やはり特定の場面で発火していませんでした。
環境はiOSで、ChromeとSafari、Firefoxでこの問題が発生しました。
自分で調べた限りではそういった仕様は見つけられませんでした。
仕様や解決策をご存知でしたら回答よろしくお願いします
ソースコード
HTML
1 2<!DOCTYPE html> 3<html> 4 <head> 5 <meta charset="utf-8" /> 6 <meta name="description" content=""> 7 <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no"> 8 <script type="text/javascript" src="script.js"></script> 9 <title>Game</title> 10 <style> 11 * { 12 padding: 0; 13 margin: 0 auto; 14 } 15 16 canvas { 17 background: #000000; 18 display: block; 19 margin: 0; 20 } 21 22 body { 23 background: #555555; 24 } 25 26 #Canvas { 27 transform-origin: top left; 28 transform: scale(1.0); 29 } 30 31 #wrapper { 32 width: 900px; 33 height: 600px; 34 margin: auto; 35 onSelectStart: "return false;"; 36 user-select: none; 37 -moz-user-select: none; 38 -webkit-user-select: none; 39 -ms-user-select: none; 40 unselectable: "on"; 41 } 42 43 body { 44 overflow: hidden; 45 } 46 </style> 47 </head> 48 <body ontouchstart=""> 49 <div id="wrapper"> 50 <canvas id="Canvas" width="900px" height="600px"></canvas> 51 </div> 52 </body> 53</html>
javascript
1window.addEventListener("DOMContentLoaded", () => { 2 const canvasEle = 3 document.getElementById("Canvas"); 4 var ctx; 5 var ext = 1; 6 7 var touches = []; 8 9 var Cwidth = 900, 10 Cheight = 600; 11 12 function game() { 13 ctx.clearRect(0, 0, Cwidth, Cheight); 14 ctx.fillStyle = "#fff"; 15 for (t of touches) { 16 const x = getTouchesXY(t)[0]; 17 ctx.fillRect(x - 5, 0, 10, 600); 18 } 19 window.requestAnimationFrame(game); 20 } 21 22 function init() { 23 ctx = canvasEle.getContext("2d"); 24 setSize(); 25 window.requestAnimationFrame(game); 26 } 27 28 canvasEle.addEventListener("touchstart", () => { 29 event.preventDefault(); 30 touches = event.touches; 31 }, { 32 passive: false 33 }); 34 35 canvasEle.addEventListener("touchmove", () => { 36 event.preventDefault(); 37 touches = event.touches; 38 }, { 39 passive: false 40 }); 41 42 canvasEle.addEventListener("touchend", () => { 43 event.preventDefault(); 44 touches = event.touches; 45 }, { 46 passive: false 47 }); 48 49 canvasEle.addEventListener("touchcancel", () => { 50 event.preventDefault(); 51 touches = event.touches; 52 }, { 53 passive: false 54 }); 55 56 function setSize() { 57 var height = window.innerHeight; 58 var width = window.innerWidth; 59 60 Cheight = 600; 61 Cwidth = Math.floor(600 * width / height); 62 canvasEle.width = Cwidth; 63 canvasEle.height = Cheight; 64 65 ext = height / 600; 66 67 canvasEle.style.width = (Cwidth * ext) + "px"; 68 canvasEle.style.height = (Cheight * ext) + "px"; 69 70 var wrap = document.getElementById('wrapper'); 71 wrap.style.width = canvasEle.style.width; 72 wrap.style.height = canvasEle.style.height; 73 } 74 75 function getTouchesXY(touch) { 76 var rect = canvasEle.getBoundingClientRect(); 77 let x = (touch.clientX - (rect.left + window.pageXOffset)) / ext; 78 let y = (touch.clientY - (rect.top + window.pageYOffset)) / ext; 79 return [x, y]; 80 } 81 82 window.addEventListener("resize", setSize); 83 window.addEventListener("orientationchange", setSize); 84 init(); 85}); 86
追記
どこか別の場所をタッチし続けておけばこのバグは発生しないことが分かりました。
恐らく他のイベントに吸われてしまっているのかと思いますが、何が原因かまでは分かりませんでした⋯

あなたの回答
tips
プレビュー