zingtouch icon indicating copy to clipboard operation
zingtouch copied to clipboard

Support Double Tap

Open clemlatz opened this issue 7 years ago • 6 comments

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.

clemlatz avatar Jan 05 '17 11:01 clemlatz

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.

mike-schultz avatar Jan 06 '17 01:01 mike-schultz

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.

mike-schultz avatar Jan 06 '17 22:01 mike-schultz

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.

clemlatz avatar Jan 06 '17 23:01 clemlatz

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

clemlatz avatar Jan 09 '17 08:01 clemlatz

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:

  1. the setTimeout method above
  2. 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.

frastlin avatar Mar 01 '19 15:03 frastlin

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();
}

ciekawy avatar Dec 05 '23 13:12 ciekawy