Re: Touch scrolling after preventDefault called on first touchmove event

On 17.04.2014, at 20:20, Timothy Dresser <tdresser@chromium.org> wrote:

> We’re thinking of modifying the way chromium behaves when the preventDefault method is called on the first touchmove event of an active touch point.. This currently prevents the active touch point from ever causing scrolling, but we are considering allowing scrolling to begin later if additional touchmove events are received which have not had their preventDefault method called. This does not deviate significantly from existing browser behaviors and increases the expressiveness of touch events in chromium.

I think that's an excellent change.

AFAIK Firefox for Android implements the spec quite literally — only the first touchmove can control scrolling, and there is no unspecified magic suppressing touchmove events (WebKit has delay/threshold that prevents touchmove being sent too early), and as a result Firefox is very hard to work with, e.g. it's impossible to reliably control scrolling in response to a "tap and hold" gesture, because user can't hold their finger without causing several (tiny) touchmove events.


I've tried to implement a scrollable list with swiping and reordering, which I think is a pretty basic building block for apps, but I found that neither touch-action nor preventDefault as currently specced offer enough control to do it well. 

My requirements were:

1. Fast vertical flick should block scrolling in both directions (swipe gesture shouldn't move the page, even if movement isn't perfectly horizontal)
1b. Ideally, slow vertical movement should allow scroll (normal behavior if movement is slower than a flick)

2. Horizontal movement should scroll, except when disabled in case 3

3. After "tap and hold" for 300ms the page should not scroll (to allow JS to drag an element)
3b. Ideally, it should be possible to scroll when the second finger touches the screen (one finger drags the element, second finger moves the page), but that's rare enough that I can do that by emulating scrolling with scrollTop/etc.

https://pornel.net/slip/

I think I could do pretty well if I could hold off native scrolling for as long as I need and let it scroll when I finish recognizing gesture user is trying to make. Otherwise, if browsers actually follow the spec as currently written, I'll have to always block scrolling on the first touchmove, then process gestures, and then resort to janky emulation of scrolling.


Can you make the better scrolling behavior feature-detectable? Maybe a special value of event.cancelable? Currently browsers set event.cancelable=true for touchmove events even when they don't listen to cancellation.


Also, while the scrolling is prevented, do those events still count towards scroll offset that will be set when scrolling is allowed? When I cease blocking scrolling, will the browser "resume" the original scroll action (finger is going to "stick" to touchstart position) or will scrolling start fresh from the point it was allowed (finger will "stick" to the first non-prevented touchmove location)? 

Let's say user touched the screen, I prevented scrolling while finger moved 100 pixels, then I allow scrolling. Will the next 1-pixel finger move change scroll offset by 101 pixels or 1 pixels?

In the former case the scroll start may look glitchy, but the page will stick to the finger like user expects. In the latter case there will be no visual jump, but from user's perspective their finger will slide by 100 pixels, which may feel unnatural.

To me either way is fine, as long as the behavior is specified, so that I can choose desired behavior by "correcting" scroll offset before letting browser scroll (or using any other method you suggest). For small moves (like a 15-pixel threshold for detecting movement direction) I'd prefer browser to follow touchstart location, so that if I don't detect a custom gesture I can pretend blocking never happened. 

-- 
regards, Kornel

Received on Friday, 18 April 2014 23:38:34 UTC