ã¿ããã¤ãã³ã
å©ç¨å¯è½æ§ã¯éå®ç
ãã®æ©è½ã¯ãã¼ã¹ã©ã¤ã³ã§ã¯ããã¾ãããæãåºã使ç¨ããã¦ãããã©ã¦ã¶ã¼ã®ä¸é¨ã§åä½ãã¾ããã
Want more support for this feature? Tell us why.
ã¿ãããã¼ã¹ã®ã¦ã¼ã¶ã¼ã¤ã³ã¿ã¼ãã§ã¤ã¹ãé«åº¦ã«ãµãã¼ãããããã端æ«ããã©ãã¯ãããã§ã®æï¼ã¾ãã¯ã¹ã¿ã¤ã©ã¹ï¼ã®åããè§£éããæ©è½ããã¿ããã¤ãã³ããæä¾ãã¾ãã
ã¿ããã¤ãã³ãã®ã¤ã³ã¿ã¼ãã§ã¤ã¹ã¯ã2 æ¬ã®æã«ããã¸ã§ã¹ãã£ã¼ãªã©ã¢ããªã±ã¼ã·ã§ã³åºæã®ãã«ãã¿ããæä½ã«å¯¾å¿ããããã«ä½¿ç¨ã§ãããæ¯è¼çä½ã¬ãã«ã® API ã§ãããã«ãã¿ããæä½ã¯ã1 æ¬ã®æï¼ã¾ãã¯ã¹ã¿ã¤ã©ã¹ï¼ãå§ãã«ã¿ããé¢ã¸ã¿ããããã¨ãããå§ã¾ãã¾ãããã®å¾ã«ä»ã®æãã¿ãããããã¨ãã§ããããã«ä»»æã§ã¿ããé¢ä¸ã§åããã¾ããæãã¿ããé¢ããé¢ãã¨ãæä½ãçµäºãã¾ããæä½ãã¦ããéãã¢ããªã±ã¼ã·ã§ã³ã¯éå§ã»ç§»åã»çµäºã®å段éä¸ã«ã¿ããã¤ãã³ããåãåãã¾ãã
ã¿ããã¤ãã³ãã¯ãã¦ã¹ã¤ãã³ãã«ä¼¼ã¦ãã¾ãããã¿ããé¢ä¸ã®ç°ãªãå ´æã§åæã«çºçããã¿ããã«å¯¾å¿ãããã¨ãç°ãªãã¾ãã TouchEvent ã¤ã³ã¿ã¼ãã§ã¤ã¹ã¯ãç¾å¨ã¢ã¯ãã£ããªãã¹ã¦ã®ã¿ããç¹ãå
å«ãã¾ãã Touch ã¤ã³ã¿ã¼ãã§ã¤ã¹ã¯ã²ã¨ã¤ã®ã¿ããç¹ã表ãããã©ã¦ã¶ã¼ã®ãã¥ã¼ãã¼ããåºæºã«ããã¿ããåæã®ä½ç½®ãªã©ã®æ
å ±ãå«ã¿ã¾ãã
å®ç¾©
- ã¿ããé¢
-
ã¿ããã«åå¿ããé¢ãç»é¢ã§ãã£ãããã©ãã¯ãããã§ãã£ããããå¯è½æ§ãããã¾ãã
- ã¿ããç¹
-
ã¿ããé¢ã«æ¥è§¦ããç¹ãããã¯æï¼ãããã¯ã²ããè³ãé¼»ãªã©ã§ãããã®ã§ãããããã¦ãæã§ãããï¼ã¾ãã¯ã¹ã¿ã¤ã©ã¹ã®å¯è½æ§ãããã¾ãã
ã¤ã³ã¿ã¼ãã§ã¤ã¹
TouchEvent-
ã¿ããé¢ã§ã¿ããç¶æ ãå¤åããã¨ãã«çºçããã¤ãã³ãã表ãã¾ãã
Touch-
ã¦ã¼ã¶ã¼ã¨ã¿ããã¿ããé¢ãæ¥ããç¹ 1 åã表ãã¾ãã
TouchList-
ã¿ããã®ã°ã«ã¼ãã表ãã¾ããä¾ãã°ãã¦ã¼ã¶ã¼ãè¤æ°ã®æãåæã«ã¿ããé¢ä¸ã«ç½®ããå ´åã«ä½¿ç¨ãã¾ãã
ä¾
ããã§ã¯ä¸åº¦ã«è¤æ°ã®ã¿ããç¹ãåå¾ãã¦ãããã¦ã¼ã¶ã¼ãä¸åº¦ã«è¤æ°ã®æã§ <canvas> ã«æããã¨ãã§ããããã«ãªã£ã¦ãã¾ãããã®ãµã³ãã«ã¯ã¿ããã¤ãã³ãã«å¯¾å¿ãã¦ãããã©ã¦ã¶ã¼ã®ã¿ã§åä½ãã¾ãã
ã¡ã¢: ããããã¯ã¿ããé¢ã¸ã®æ¥è§¦ã表ãã¨ãã«ãæãã¨ãã表ç¾ã使ç¨ãã¾ãããå½ç¶ãªããã¹ã¿ã¤ã©ã¹ãªã©ä»ã®æ¥è§¦æ³ã使ç¨ã§ãã¾ãã
ãã£ã³ãã¹ã®ä½æ
<canvas id="canvas" width="600" height="600" style="border:solid black 1px;">
ãã®ãã©ã¦ã¶ã¼ã¯ canvas è¦ç´ ã«å¯¾å¿ãã¦ãã¾ããã
</canvas>
<br />
Log:
<pre id="log" style="border: 1px solid #ccc;"></pre>
#log {
height: 200px;
width: 600px;
overflow: scroll;
}
ã¤ãã³ããã³ãã©ã¼ã®è¨å®
ãã¼ã¸ãèªã¿è¾¼ãã¨ãã以ä¸ã® startup() 颿°ãå¼ã³åºããã¾ãã
ããã§ <canvas> è¦ç´ ã¸ãã¹ã¦ã®ã¤ãã³ããªã¹ãã¼ãè¨å®ãã¦ãããã¿ããã¤ãã³ãã®çºçã«å¿ãã¦æ±ããã¨ãã§ããããã«ãªãã¾ãã
function startup() {
const el = document.getElementById("canvas");
el.addEventListener("touchstart", handleStart);
el.addEventListener("touchend", handleEnd);
el.addEventListener("touchcancel", handleCancel);
el.addEventListener("touchmove", handleMove);
log("Initialized.");
}
document.addEventListener("DOMContentLoaded", startup);
æ°ããªã¿ããã®è¿½è·¡
é²è¡ä¸ã®ã¿ããã追跡ãç¶ãã¾ãã
const ongoingTouches = [];
ã¿ããé¢ä¸ã§æ°ããªã¿ãããçºçãããã¨ã示ã touchstart ã¤ãã³ããçºçããã¨ãhandleStart() 颿°ãå¼ã³åºãã¾ãã
function handleStart(evt) {
evt.preventDefault();
log("touchstart.");
const el = document.getElementById("canvas");
const ctx = el.getContext("2d");
const touches = evt.changedTouches;
for (let i = 0; i < touches.length; i++) {
log(`touchstart: ${i}.`);
ongoingTouches.push(copyTouch(touches[i]));
const color = colorForTouch(touches[i]);
log(`color of touch with id ${touches[i].identifier} = ${color}`);
ctx.beginPath();
ctx.arc(touches[i].pageX, touches[i].pageY, 4, 0, 2 * Math.PI, false); // æåã«åãæã
ctx.fillStyle = color;
ctx.fill();
}
}
ããã§ã¯ããã©ã¦ã¶ã¼ãã¿ããã¤ãã³ãã®å¦çãç¶ããªãããã«ãããã event.preventDefault() ãå¼ã³åºãã¾ã (ã¾ãããã¦ã¹ã¤ãã³ãã®ä¼éãææ¢ãã¾ã)ãããã¦ã³ã³ããã¹ããåå¾ãã¦ãã¤ãã³ãã® TouchEvent.changedTouches ããããã£ããå¤åããã¿ããç¹ã®ãªã¹ããåãè¾¼ã¿ã¾ãã
ãã®å¾ã«ããªã¹ãå
ã®ãã¹ã¦ã® Touch ãªãã¸ã§ã¯ããèµ°æ»ãã¦ã¢ã¯ãã£ããªã¿ããç¹ã®é
åã«éãè¾¼ã¿ãæç»ãéå§ããä½ç½®ã«å°ããªä¸¸å°ãæç»ãã¾ãããã®ä¾ã§ã¯ 4 ãã¯ã»ã«å¹
ã®ç·ã使ç¨ãã¾ãã®ã§ãåå¾ 4 ãã¯ã»ã«ã®åããããã«è¦ãã¾ãã
ã¿ããã®ç§»åã«åãããæç»
1 æ¬ä»¥ä¸ã®æãç§»åãããã³ã« touchmove ã¤ãã³ããçºçãã¾ãã®ã§ããã®çµæ handleMove() 颿°ãå¼ã³åºããã¾ããããã¯ãã£ãã·ã¥ããã¿ããæ
å ±ãæ´æ°ãã¦ãã¿ãããã¨ã«ä»¥åã®ä½ç½®ããç¾å¨ã®ä½ç½®ã¾ã§ç·ãæç»ããå½¹å²ãæ
ã£ã¦ãã¾ãã
function handleMove(evt) {
evt.preventDefault();
const el = document.getElementById("canvas");
const ctx = el.getContext("2d");
const touches = evt.changedTouches;
for (let i = 0; i < touches.length; i++) {
const color = colorForTouch(touches[i]);
const idx = ongoingTouchIndexById(touches[i].identifier);
if (idx >= 0) {
log(`continuing touch ${idx}`);
ctx.beginPath();
log(
`ctx.moveTo( ${ongoingTouches[idx].pageX}, ${ongoingTouches[idx].pageY} );`,
);
ctx.moveTo(ongoingTouches[idx].pageX, ongoingTouches[idx].pageY);
log(`ctx.lineTo( ${touches[i].pageX}, ${touches[i].pageY} );`);
ctx.lineTo(touches[i].pageX, touches[i].pageY);
ctx.lineWidth = 4;
ctx.strokeStyle = color;
ctx.stroke();
ongoingTouches.splice(idx, 1, copyTouch(touches[i])); // swap in the new touch record
} else {
log("can't figure out which touch to continue");
}
}
}
ããã¯åæ§ã«å¤æ´ãããã¿ããã«å¯¾ãã¦èµ°æ»ãã¦ãã¾ãããåã¿ããã§æ°ãã«æç»ããç·åã®éå§ç¹ãæ¤åºããããã«ãåã¿ããã®ä»¥åã®æ
å ±ã«ã¤ãã¦ãã£ãã·ã¥ããã¿ããæ
å ±ã®é
åãåç
§ãã¦ãã¾ããããã¯ãåã¿ããã® Touch.identifier ããããã£ã確èªãã¦è¡ãã¾ãããã®ããããã£ã¯åã¿ããã§ä¸æã®èå¥åã§ãããæã¨ã¿ããé¢ã¨ã®æ¥è§¦ãç¶ãã¦ããéãå¤ãåºå®ããã¾ãã
ããã«ããåã¿ããã®åã®ä½ç½®ã®åº§æ¨ãåå¾ãã¦ã2 ã¤ã®ç¹ãçµã¶ç·åãæç»ããããã«é©åãªã³ã³ããã¹ãã¡ã½ããã使ç¨ã§ãã¾ãã
ç·åãæç»ããå¾ãåã®ã¿ããç¹ã®æ
å ±ã ongoingTouches é
åå
ã«ããç¾å¨ã®æ
å ±ã«ç½®ãæãããããArray.splice() ãå¼ã³åºãã¾ãã
ã¿ããã®çµäºãå¶å¾¡ãã
ã¦ã¼ã¶ã¼ãã¿ããé¢ããæãé¢ã㨠touchend ã¤ãã³ããçºçãã¾ããç§ãã¡ã¯ãããã®ä¸¡æ¹ãã以ä¸ã® handleEnd() 颿°ãå¼ã³åºãã¨ããã²ã¨ã¤ã®æ¹æ³ã§æ±ãã¾ãããã®é¢æ°ã®å½¹å²ã¯ãçµäºããã¿ããã«ã¤ãã¦æå¾ã®ç·åãæç»ãããã¨ã¨ãç¶ç¶ä¸ã®ã¿ããã®ãªã¹ãããã¿ããç¹ãåé¤ãããã¨ã§ãã
function handleEnd(evt) {
evt.preventDefault();
log("touchend");
const el = document.getElementById("canvas");
const ctx = el.getContext("2d");
const touches = evt.changedTouches;
for (let i = 0; i < touches.length; i++) {
const color = colorForTouch(touches[i]);
let idx = ongoingTouchIndexById(touches[i].identifier);
if (idx >= 0) {
ctx.lineWidth = 4;
ctx.fillStyle = color;
ctx.beginPath();
ctx.moveTo(ongoingTouches[idx].pageX, ongoingTouches[idx].pageY);
ctx.lineTo(touches[i].pageX, touches[i].pageY);
ctx.fillRect(touches[i].pageX - 4, touches[i].pageY - 4, 8, 8); // and a square at the end
ongoingTouches.splice(idx, 1); // remove it; we're done
} else {
log("can't figure out which touch to end");
}
}
}
ããã¯åã®é¢æ°ã«ã¨ã¦ãä¼¼ã¦ãã¾ãããçµç«¯ã表ãå°ããªåè§å½¢ãæç»ãããã¨ã¨ãArray.splice() ãå¼ã³åºãã¦ãæ´æ°å¾ã®æ
å ±ã追å ããã«ç¶ç¶ä¸ã®ã¿ãããªã¹ãããå¤ãé
ç®ãåé¤ãããã¨ãç°ãªãã¾ãããã®çµæãã¿ããç¹ã®è¿½è·¡ã忢ãã¾ãã
åãæ¶ãããã¿ãããå¶å¾¡ãã
ã¦ã¼ã¶ã¼ã®æããã©ã¦ã¶ã¼ã® UI ã«å
¥ãè¾¼ãã ãããã®ä»ã«ã¿ããããã£ã³ã»ã«ããªããã°ãªããªãã¨ãã«ã¯ touchcancel ã¤ãã³ããçºçãã¦ã以ä¸ã® handleCancel() 颿°ãå®è¡ããã¾ãã
function handleCancel(evt) {
evt.preventDefault();
log("touchcancel.");
const touches = evt.changedTouches;
for (let i = 0; i < touches.length; i++) {
let idx = ongoingTouchIndexById(touches[i].identifier);
ongoingTouches.splice(idx, 1); // remove it; we're done
}
}
å³åº§ã«ã¿ãããåãæ¶ãã¨ããèãæ¹ããæçµã®ç·åãæç»ããã«ãç¶ç¶ä¸ã®ã¿ãããªã¹ãããåç´ã«ã¿ãããåé¤ãã¾ãã
便å©ãªé¢æ°
ãã®ä¾ã§ã¯ã³ã¼ãã®æ®ãã®é¨åãããæç¢ºã«ãããã¨ãå©ãããç°¡åã«è¦ã¦ããã¹ãã§ãã 2 ã¤ã®ä¾¿å©ãªé¢æ°ã使ç¨ãã¦ãã¾ãã
ããããã®ã¿ããã®è²ã鏿ãã
ããããã®ã¿ããã®å¤è¦ãåºå¥ãã¦æç»ããããã«ãã¿ããã®ä¸æãªèå¥åãå
ã«è²ã鏿ãã colorForTouch() 颿°ã使ç¨ãã¾ãããã®èå¥åã¯ä¸æçãªæ°å¤ã§ãããå°ãªãã¨ãç¾å¨ã¢ã¯ãã£ããªã¿ãããåºå¥ãããã¨ã¯ã§ãã¾ãã
function colorForTouch(touch) {
let r = touch.identifier % 16;
let g = Math.floor(touch.identifier / 3) % 16;
let b = Math.floor(touch.identifier / 7) % 16;
r = r.toString(16); // make it a hex digit
g = g.toString(16); // make it a hex digit
b = b.toString(16); // make it a hex digit
const color = `#${r}${g}${b}`;
return color;
}
ãã®é¢æ°ã®è¿å¤ã¯ãæç»è²ãè¨å®ããããã« <canvas> 颿°ãå¼ã³åºãã¨ãã«ä½¿ç¨ã§ããæååã§ããä¾ãã° Touch.identifier ã®å¤ã 10 ã§ããã°ãè¿å¤ã¯æåå "#a31" ã«ãªãã¾ãã
touch ãªãã¸ã§ã¯ãã®ã³ãã¼
ä¸é¨ã®ãã©ã¦ã¶ã¼ (ä¾ãã°ã¢ãã¤ã«ç Safari) ã¯ã¤ãã³ãéã§ touch ãªãã¸ã§ã¯ããå使ç¨ããããããªãã¸ã§ã¯ãå ¨ä½ãåç §ããããããé¢å¿ãããé¨åãã³ãã¼ããã»ããæåã§ãã
function copyTouch({ identifier, pageX, pageY }) {
return { identifier, pageX, pageY };
}
ç¶ç¶ä¸ã®ã¿ãããè¦ã¤ãã
以ä¸ã® ongoingTouchIndexById() 颿°ã¯ãæå®ããèå¥åã«ä¸è´ããã¿ãããè¦ã¤ããããã«é
å ongoingTouches ãæ¢ç´¢ãã¦ããã®ã¿ããã®é
åå
ã«ãããã¤ã³ããã¯ã¹ãè¿ãã¾ãã
function ongoingTouchIndexById(idToFind) {
for (let i = 0; i < ongoingTouches.length; i++) {
const id = ongoingTouches[i].identifier;
if (id === idToFind) {
return i;
}
}
return -1; // è¦ã¤ãããªã
}
ä½ãè¡ã£ã¦ããã表示
function log(msg) {
const container = document.getElementById("log");
container.textContent = `${msg} \n${container.textContent}`;
}
çµæ
ãã®ä¾ã¯ãä¸è¨ã®ããã¯ã¹ãã¿ãããããã¨ã§ãã¢ãã¤ã«ç«¯æ«ã§ãã¹ããããã¨ãã§ãã¾ãã
ã¡ã¢: ä¸è¬çã«ã¯ã ãã®ä¾ã¯ã¿ããã¤ãã³ããæä¾ãããã©ãããã©ã¼ã ã§åä½ãã¾ãã ãã®ãããªã¤ãã³ããã·ãã¥ã¬ã¼ãã§ãããã¹ã¯ããããã©ãããã©ã¼ã ã§ãã¹ããããã¨ãã§ãã¾ãã
- Firefox ã§ã¯ã¬ã¹ãã³ã·ããã¶ã¤ã³ã¢ã¼ãã®ãã¿ããã·ãã¥ã¬ã¼ã·ã§ã³ããæå¹ã«ãã¦ãã ããï¼ãã¼ã¸ã®åèªã¿è¾¼ã¿ãå¿ è¦ãªå ´åãããã¾ãï¼ã
- Chrome ã§ã¯ããã¤ã¹ã¢ã¼ãã使ç¨ããããã¤ã¹ã¿ã¤ããã¿ããã¤ãã³ããéä¿¡ãããã®ã«è¨å®ãã¦ãã ããã
追å ã®è±ç¥è
ãã®ç« ã§ã¯ã¦ã§ãã¢ããªã±ã¼ã·ã§ã³ã§ã¿ããã¤ãã³ããæ±ãæ¹æ³ã«ã¤ãã¦ã追å ã®è±ç¥èãç´¹ä»ãã¾ãã
ã¯ãªãã¯ãå¶å¾¡ãã
preventDefault() ã touchstart ã¾ãã¯ä¸é£ã®ä¸ã§æåã® touchmove ã§å¼ã³åºãã¨ã対å¿ãããã¦ã¹ã¤ãã³ãã®çºçãæå¶ã§ããããã preventDefault() 㯠touchstart ããã touchmove ã§å¼ã³åºããã¨ãä¸è¬çã§ãããã®æ¹æ³ã§ã¯å¾æ¥ã©ãããã¦ã¹ã¤ãã³ããçºçãã¦ããªã³ã¯ãªã©ãå¼ãç¶ãåä½ãã¾ãã代ããã«ä¸é¨ã®ãã¬ã¼ã ã¯ã¼ã¯ã§ã¯åæ§ã®ç®çã§ãã¿ããã¤ãã³ãããã¦ã¹ã¤ãã³ãã¨ãã¦åçºçããã¦ãã¾ããï¼ãã®ä¾ã¯é度ã«åç´åãã¦ãããå¥å¦ãªåä½ã«ãªãããããã¾ãããã¬ã¤ãã¨ãã¦æ²è¼ãã¦ããã«éãã¾ãããï¼
function onTouch(evt) {
evt.preventDefault();
if (
evt.touches.length > 1 ||
(evt.type === "touchend" && evt.touches.length > 0)
)
return;
const newEvt = document.createEvent("MouseEvents");
let type = null;
let touch = null;
switch (evt.type) {
case "touchstart":
type = "mousedown";
touch = evt.changedTouches[0];
break;
case "touchmove":
type = "mousemove";
touch = evt.changedTouches[0];
break;
case "touchend":
type = "mouseup";
touch = evt.changedTouches[0];
break;
}
newEvt.initMouseEvent(
type,
true,
true,
evt.originalTarget.ownerDocument.defaultView,
0,
touch.screenX,
touch.screenY,
touch.clientX,
touch.clientY,
evt.ctrlKey,
evt.altKey,
evt.shiftKey,
evt.metaKey,
0,
null,
);
evt.originalTarget.dispatchEvent(newEvt);
}
2 çªç®ã®ã¿ããã®ã¿ã§ preventDefault() ãå¼ã³åºã
ãã¼ã¸ä¸ã§ pinchZoom ã¨ãã£ãæä½ãé²ããã¯ããã¯ã®ã²ã¨ã¤ã¨ãã¦ãä¸é£ã®ã¿ããã® 2 çªç®ã§ preventDefault() ãå¼ã³åºãæ¹æ³ãããã¾ãããã®åä½ã¯ã¿ããã¤ãã³ãã®ä»æ§æ¸ã§æç¤ºããã¦ãããããã©ã¦ã¶ã¼ã«ãã£ã¦çµæãç°ãªãã¾ã (iOS ã§ã¯ãºã¼ã ãé²ãã¾ããããã³ã¯å¯è½ã§ããAndroid ã¯ãºã¼ã ãå¯è½ã§ããããã³ã¯ã§ãã¾ãããOpera ããã³ Firefox ã¯ç¾ç¶ããã³ããºã¼ã ãé²ãã¾ã)ãç¾å¨ããã®ã±ã¼ã¹ã§ç¹å®ã®åä½ã«ä¾åãããã¨ã¯æ¨å¥¨ããããã¡ã¿ãã¥ã¼ãã¼ãã®ãºã¼ã ãé²ãã¨èãã¦ãã ããã
仿§æ¸
| 仿§æ¸ |
|---|
| Touch Events > |
ãã©ã¦ã¶ã¼ã®äºææ§
ã¿ããã¤ãã³ãã¯é常ãã¿ããç»é¢ãåãã端æ«ã§ä½¿ç¨ã§ãã¾ãããå¤ãã®ãã©ã¦ã¶ã¼ã¯ãã¿ããç»é¢ãåãããã®ã§ãã£ã¦ãããã¹ã¦ã®ãã¹ã¯ããã端æ«ã§ã¿ããã¤ãã³ã API ãã§ããªãããã«ãã¦ãã¾ãã
ããã¯ãä¸é¨ã®ã¦ã§ããµã¤ãã§ãã¿ããã¤ãã³ã API ã®ä¸é¨ãå©ç¨ã§ãããã¨ãããã©ã¦ã¶ã¼ãã¢ãã¤ã«ç«¯æ«ã§å®è¡ããã¦ãããã¨ãç¤ºãææ¨ã¨ãã¦ä½¿ç¨ããã¦ããããã§ããã¿ããã¤ãã³ã API ãå©ç¨å¯è½ãªå ´åããããã®ã¦ã§ããµã¤ãã¯ã¢ãã¤ã«ç«¯æ«ãæ³å®ããã¢ãã¤ã«ã«æé©åãããã³ã³ãã³ããé ä¿¡ãã¾ãããã®çµæãã¿ããç»é¢ãæè¼ãããã¹ã¯ããã端æ«ã®ã¦ã¼ã¶ã¼ã«ã¨ã£ã¦ã¯ã使ãåæãæªããªãå¯è½æ§ãããã¾ãã
ãã¹ã¦ã®ç¨®é¡ã®ç«¯æ«ã§ã¿ããã¨ãã¦ã¹ã®ä¸¡æ¹ã«å¯¾å¿ããã«ã¯ã代ããã«ãã¤ã³ã¿ã¼ã¤ãã³ãã使ç¨ãã¦ãã ããã