zingtouch
zingtouch copied to clipboard
Support Double Tap
Any plans to support double tap ?
If I'm not mistaken, this is not supported by ZingTouch yet. I tried to use the numInputs
option of the Tap
gesture only to understand that it was for the number of fingers, not the number of taps in time.
I feel that double tap is a common use case in touch screens UI and frequently implemented in other multi-touch libraries. I think this would be a useful addition to ZingTouch.
Yeah I agree that's a good gesture to be implemented. A little bit of work will need to be done throughout the code since all of the existing gestures reset after all inputs leave the screen; different in the case of a double tap.
I did some work towards it, but there are a couple issues towards it. ZingTouch's logic predicates gestures as a on-screen event ending when all inputs off screen. Double-tap is a unique gesture where we would need to track the progress across multiple events. Currently the architecture does not support that and it would either have to be redone, or hacked around to make it work.
In addition, double-taps on mobile devices won't work unless the touch area is specified to have preventDefault on. Double-tap usually means a browser-level zoom.
Do you have any specific use cases for double tap? We're trying to see if this is worth while to re-architect the library for this gesture.
Thanks Mike for your work so far.
I'm working on a digital comics reader and I'm looking for a multi-touch gesture library to implement controlling zoom level on a image with pinch, expand and double-tap. I've tried Hammer.js who supports double tap but I feel it lacks precision so I'd rather use ZingTouch.
I have a prototype using ZingTouch where I detect two ZintTouch Tap
events using setTimeout
(sadly I cannot show it to you right now because it's on my office's computer and I won't have access to it until Monday). It felt a little hacky and I felt it would be cleaner with a DoubleTap
event, hence the issue.
Anyway, I can live with it, maybe don't bother if it means you need to rewrite the whole library.
Here's my prototype with specific use case using expand, pinch, and manually-implemented double tap to manipulated an image (a blue rectangle in the prototype) : https://gist.github.com/iwazaru/058b4dfad18d37d751d46884b261c967
I would also like double tap for a game I'm making. I could also really use triple tap as well. I could see 2 possible ways of doing this:
- the setTimeout method above
- have the last tap events saved in a list and if the last tap event's timestamp is within the listening period, and the fingers match on both events, then run the double tap event. This method could push the last event and also check for the length of the number of tap events. This would allow for as many tap events as one specifies, so one could technically have a 10 tap if they really wanted. This could either be on the tap event options as numberOfTaps, or a new event type could be created called multiTap.
here is generic gesture sequence handler - it can be used for simple stuff like double-tap or for sequence of predefined gestures, e.g four fingers double tap:
bindGestureSequence(
new ZingTouch.Region(gestureArea, false, false),
gestureArea,
[
new ZingTouch.Tap({ numInputs: 4 }),
new ZingTouch.Tap({ numInputs: 4 }),
],
() => {
console.log(
'=== 2x4tap, handlers.length',
gestureHandlers.length,
);
gestureHandlers.forEach((handler) => handler());
},
)
function bindGestureSequence(
region,
area,
gestureArray,
handlerOnAllGestures,
timeout = 300,
) {
let currentGestureIndex = 0;
let gestureTimeout;
const clearGestureSequence = () => {
clearTimeout(gestureTimeout);
currentGestureIndex = 0;
};
const sequenceHandler = (e) => {
console.log(
gestureArray[currentGestureIndex]?.constructor?.name,
e,
);
// Clear the previous timeout
clearTimeout(gestureTimeout);
// Check if the gesture is the expected one in the sequence
if (
gestureArray[currentGestureIndex] /* &&
e.detail.type === gestureArray[currentGestureIndex].type*/
) {
currentGestureIndex++;
// Check if the entire sequence has been completed
if (currentGestureIndex >= gestureArray.length) {
clearGestureSequence();
handlerOnAllGestures();
return;
}
// Set up the next gesture in the sequence
setupNextGesture();
} else {
// Reset if the gesture is not as expected
clearGestureSequence();
}
};
const setupNextGesture = () => {
const currentGesture = gestureArray[currentGestureIndex];
region.unbind(area, currentGesture); // Unbind the previous gesture
region.bind(area, currentGesture, sequenceHandler);
// Set a timeout to reset the sequence if the next gesture doesn't occur in time
gestureTimeout = setTimeout(() => {
clearGestureSequence();
setupNextGesture(); // Rebind the first gesture to start over
}, timeout);
};
// Start the sequence by binding the first gesture
setupNextGesture();
}