実現したいこと
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
追記
どこか別の場所をタッチし続けておけばこのバグは発生しないことが分かりました。
恐らく他のイベントに吸われてしまっているのかと思いますが、何が原因かまでは分かりませんでした⋯
まずは問題の発生するコードをご提示ください。
すいません
ソースコードです。
両方とも汚くて申し訳ありません⋯
jsの方はバグに関係無いところをカットしました
どうやら画面縦向きだとこのバグは起きないようです
(横向き前提で作っていたので気づきませんでした⋯)
よろしくお願いします
HTML----------
<!DOCTYPE html><html><head> <meta charset="utf-8"/> <meta name="description" content=""> <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no"> <script type="text/javascript" src="script.js"></script> <title>Game</title> <style>*{padding: 0; margin: 0 auto;}canvas{background: #000000; display: block; margin: 0;}body{background: #555555;}#Canvas{transform-origin: top left; transform: scale(1.0);}#wrapper{width: 900px; height: 600px; margin: auto;onSelectStart:"return false;";user-select:none; -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none;unselectable:"on";}body{overflow: hidden;}</style></head><body ontouchstart=""><div id="wrapper"><canvas id="Canvas" width="900px" height="600px"></canvas></div></body></html>
js-----------
window.addEventListener("DOMContentLoaded",()=>{
const canvasEle=
document.getElementById("Canvas");
var ctx;
var ext=1;
var touches=[];
var Cwidth=900,Cheight=600;
function game(){
ctx.clearRect(0,0,Cwidth,Cheight);
ctx.fillStyle="#fff";
for(t of touches){
const x=getTouchesXY(t)[0];
ctx.fillRect(x-5,0,10,600);
}
window.requestAnimationFrame(game);
}
function init(){
ctx = canvasEle.getContext("2d");
setSize();
window.requestAnimationFrame(game);
}
canvasEle.addEventListener("touchstart",()=>{
event.preventDefault();
touches=event.touches;
},{passive:false});
canvasEle.addEventListener("touchmove",()=>{
event.preventDefault();
touches=event.touches;
},{passive:false});
canvasEle.addEventListener("touchend",()=>{
event.preventDefault();
touches=event.touches;
},{passive:false});
canvasEle.addEventListener("touchcancel",()=>{
event.preventDefault();
touches=event.touches;
},{passive:false});
function setSize(){
var height=window.innerHeight;
var width=window.innerWidth;
Cheight=600;Cwidth=Math.floor(600*width/height);
canvasEle.width=Cwidth;
canvasEle.height=Cheight;
ext=height/600;
canvasEle.style.width=(Cwidth*ext)+"px";
canvasEle.style.height=(Cheight*ext)+"px";
var wrap=document.getElementById('wrapper');
wrap.style.width=canvasEle.style.width;
wrap.style.height=canvasEle.style.height;
}
function getTouchesXY(touch){
var rect = canvasEle.getBoundingClientRect();
let x=(touch.clientX-(rect.left + window.pageXOffset))/ext;
let y=(touch.clientY-(rect.top + window.pageYOffset))/ext;return [x,y];
}
window.addEventListener("resize", setSize);
window.addEventListener("orientationchange",setSize);
init();
});
質問は編集できますので本文に追記を。
また、コードはマークダウンでご提示を。
あなたの回答
tips
プレビュー