JavaScript Mapping Touch Events to Mouse Events

JavaScript mapping touch events to mouse events

I am sure this is what you want:

function touchHandler(event)
{
var touches = event.changedTouches,
first = touches[0],
type = "";
switch(event.type)
{
case "touchstart": type = "mousedown"; break;
case "touchmove": type = "mousemove"; break;
case "touchend": type = "mouseup"; break;
default: return;
}

// initMouseEvent(type, canBubble, cancelable, view, clickCount,
// screenX, screenY, clientX, clientY, ctrlKey,
// altKey, shiftKey, metaKey, button, relatedTarget);

var simulatedEvent = document.createEvent("MouseEvent");
simulatedEvent.initMouseEvent(type, true, true, window, 1,
first.screenX, first.screenY,
first.clientX, first.clientY, false,
false, false, false, 0/*left*/, null);

first.target.dispatchEvent(simulatedEvent);
event.preventDefault();
}

function init()
{
document.addEventListener("touchstart", touchHandler, true);
document.addEventListener("touchmove", touchHandler, true);
document.addEventListener("touchend", touchHandler, true);
document.addEventListener("touchcancel", touchHandler, true);
}

I've captured the touch events and then manually fired my own mouse events to match. Although the code isn't particularly general purpose as is, it should be trivial to adapt to most existing drag and drop libraries, and probably most existing mouse event code. Hopefully this idea will come in handy to people developing web applications for the iPhone.

Update:

In posting this, I noticed that calling preventDefault on all touch events will prevent links from working properly. The main reason to call preventDefault at all is to stop the phone from scrolling, and you can do that by calling it only on the touchmove callback. The only downside to doing it this way is that the iPhone will sometimes display its hover popup over the drag origin. If I discover a way to prevent that, I'll update this post.

Second Update:

I've found the CSS property to turn off the callout: -webkit-touch-callout.

Need to convert Mouse events to Touch Events for mobile using HTML Canvas

Actually it is as easy as listening for both - touch and mouse - events.
The touchstart event is the mousedown, the touchmove the mousemove and lastly touchend is the mouseup equivalent.

Theoretically you could simply add the same callback functions to all of these listeners. The only problem is you can't directly query the 'mouse' position using the event.clientX property inside the callback function. That's because there can be multiple touches while there is always just a single mouse event. To keep track of the touches, those are stored in a TouchList - more or less an array - which is the .touches property of the event.

So we need to make a distinction between a mouse and a touch event inside the callback function:

  • If it's a touch use event.touches[0].clientX
  • If it's a mouse event use event.clientX

Here's an example based on your code:

var canvas = document.createElement('canvas');
canvas.id = "canvas";
document.body.appendChild(canvas);

document.body.style.margin = 0;
canvas.style.position = 'relative';

var ctx = canvas.getContext('2d');
resize();

var pos = {
x: 0,
y: 0
};
var buttonDown = false;

const cvs = document.getElementById("canvas");
cvs.addEventListener('mousedown', getRandomInt);
cvs.addEventListener('touchstart', getRandomInt);

window.addEventListener('resize', resize);

document.addEventListener('mousemove', draw);
document.addEventListener('mousedown', setPosition);
document.addEventListener('mouseup', released);

document.addEventListener('touchstart', setPosition);
document.addEventListener('touchmove', draw);
document.addEventListener('touchend', released);

function getRandomInt() {
window.randInt = Math.floor(Math.random() * Math.floor(3));
}

function released(e) {
buttonDown = false;
}

function setPosition(e) {
if (e.type == "touchstart" || e.type == "mousedown") {
buttonDown = true;
}
if (e.type == "touchstart" || e.type == "touchmove") {
pos.x = e.touches[0].clientX;
pos.y = e.touches[0].clientY;
} else {
pos.x = e.clientX;
pos.y = e.clientY;
}
}

function resize() {
ctx.canvas.width = window.innerWidth;
ctx.canvas.height = window.innerHeight;
}

function draw(e) {
if (!buttonDown) return;

var color = '';

switch (window.randInt) {
case 1:
color = 'green';
break;
case 2:
color = 'red';
break;
case 0:
color = 'blue';
break;
}

ctx.beginPath();

ctx.lineWidth = 3;
ctx.lineCap = 'round';
ctx.strokeStyle = color;

ctx.moveTo(pos.x, pos.y);
setPosition(e);
ctx.lineTo(pos.x, pos.y);

ctx.stroke();
}

handle both mouse and touch events on touch screens

You should rather check availability of touch interface and bind events according to that.

You can do something like this:

(function () {
if ('ontouchstart' in window) {
window.Evt = {
PUSH : 'touchstart',
MOVE : 'touchmove',
RELEASE : 'touchend'
};
} else {
window.Evt = {
PUSH : 'mousedown',
MOVE : 'mousemove',
RELEASE : 'mouseup'
};
}
}());

// and then...

document.getElementById('mydiv').addEventListener(Evt.PUSH, myStartDragHandler, false);


If you want to handle both in same time and browser does not translate well touch events into mouse events, you can catch touch events and stop them - then corresponding mouse event shouldn't be fired by browser (you won't have double events) and you can fire it yourself as mouse event or just handle it.

var mydiv = document.getElementsById('mydiv');
mydiv.addEventListener('mousemove', myMoveHandler, false);
mydiv.addEventListener('touchmove', function (e) {
// stop touch event
e.stopPropagation();
e.preventDefault();

// translate to mouse event
var clkEvt = document.createEvent('MouseEvent');
clkEvt.initMouseEvent('mousemove', true, true, window, e.detail,
e.touches[0].screenX, e.touches[0].screenY,
e.touches[0].clientX, e.touches[0].clientY,
false, false, false, false,
0, null);
mydiv.dispatchEvent(clkEvt);

// or just handle touch event
myMoveHandler(e);
}, false);

mouse events to touch event for ipad compatibility

You can map it like this:

$('#drawingCanvas').bind("mousedown touchstart", function(e){

$('#drawingCanvas').bind("mousemove touchmove", function(e){

$('#drawingCanvas').bind("mouseup touchend", function(e){

And than finetune the code if needed.

Touch event for mouseover

Virtual mouse event by JQuery mobile
is quite welldone.
https://api.jquerymobile.com/vmouseover/



Related Topics



Leave a reply



Submit