Is there any difference between writing JS touch events for iPad vs. iPhone? I have read a ton of documentation and as far as I can tell it should work the same way for both.
I have a drag-and-drop game, basically you grab a coin from under the dragon and drag it over to your vault. The dragging works on iPad, but not on iPhone. I'm trying to figure out why.
The game, for reference: https://codeeverydamnday.com/projects/dragondrop/dragondrop.html
The JS, abridged to just the relevant code for this question (with comments for clarity):
var dragndrop = (function() {
var myX = "";
var myY = "";
// The coin's starting X and Y coordinate positions
var coin = "";
// The coin you start touching / dragging
function touchStart(e) {
e.preventDefault();
// Prevents default behavior of scrolling when you touch/drag on mobile
var coin = e.target;
var touch = e.touches[0];
var moveOffsetX = coin.offsetLeft - touch.pageX;
var moveOffsetY = coin.offsetTop - touch.pageY;
// Defines offset between left edge of coin and where you place your finger on it
coin.addEventListener('touchmove', function() {
var positionX = touch.pageX+moveOffsetX;
var positionY = touch.pageY+moveOffsetY;
// Defines the X-Y coordinates of wherever you stop dragging
coin.style.left = positionX + 'px';
coin.style.top = positionY + 'px';
// Updates the coin's X-Y coordinates with the new positions
}, false)
}
document.querySelector('body').addEventListener('touchstart', touchStart, false);
})();
If it helps, I am getting this console log error every time I click / tap on the iPad screen in the Chrome Dev Tools emulator:
[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive.
This error doesn't seem to prevent the dragging from working on iPad, but I'm not sure if it has anything to do with the dragging not working on mobile? I tried adding a few things to fix the error based on other Stack Overflow questions I saw (ex. adding touch-action: none;
in my CSS, but the error persisted).
Anyone see anything wrong in my code? I would love to get this game playable on mobile, as that's how most people would access it!
The default value of the passive option is set to true
for touch-start
and touch-move
events, and it being true means your function won't call preventDefault
to disable scrolling.
Simply set the passive
value to false
to solve your issue.
var dragndrop = (function() {
var myX;
var myY;
var coin;
function touchStart(e) {
e.preventDefault();
coin = e.target;
const touch = e.touches[0];
const moveOffsetX = whichArt.offsetLeft - touch.pageX;
const moveOffsetY = whichArt.offsetTop - touch.pageY;
coin.addEventListener("touchmove", touchMove, { passive: false });
function touchMove(e) {
const touch = e.touches[0];
const positionX = touch.pageX + moveOffsetX;
const positionY = touch.pageY + moveOffsetY;
coin.style.left = `${positionX}px`;
coin.style.top = `${positionY}px`;
}
}
document.body.addEventListener('touchstart', touchStart, { passive: false });
})();
I looked at the code from the website you linked, and I realized that one reason the coin wasn't dragged was because of touch
we were using and also because of the once
option I passed to the touchmove
event.
Whenever the touchmove
event is used, we have to use the new touch to get the pageX
and pageY
positions on the screen, I decided to create a function for the touchmove
event, because whenever the touchstart
function is called, a new touchmove
event is registered because of the anonymous function handler.
So creating and naming a function for it will prevent the same function from being added.