taataa / tapspace

Zoomable user interface library for web apps.
https://taataa.github.io/tapspace/
MIT License
58 stars 8 forks source link

Do not use stopPropagation #98

Closed axelpale closed 6 years ago

axelpale commented 6 years ago

There are risks in using stopPropagation. The current Touchable uses it a lot. Let us analyse why we used it in the first place and then try to implement the desired behaviour in a better way.

Background

With ev.stopPropagation() we prevented gesture recognition to happen on multiple items at the same time. The topmost Touchable captured all the events and stopped all.

However, this led to a problem when we wanted to recognize gestures concurrently on multiple nested items:

The problem caused us to implement propagate property into Touchable mode. With propagate: true the events were allowed to propagate from items to view, where they were finally stopped. The example Tiles made use of this and provided a dense grid of items that could be rotated by tapping, but still keeping the view transformable.

The issue is briefly discussed in https://github.com/taataa/tapspace/issues/62

Proposition

Enforce stronger separation between transform and tap events. Do not emit gesturestart etc if only tap is enabled. Topmost transformation recognizer wins. Topmost tap recognizer share with all other tap recognizers. Tap does not cancel transformations. Transformations do not cancel tap. Taps do not cancel each other.

So, let the events bubble but mark as transformation-handled those events that take part in transformation recognition. A transformation handled event is respected in recognition of tap but does not contribute in item's transformation or emission of gesture events.

Naming contradiction: tap is a gesture and therefore gesturestart etc are a misleadingly named. Before tapspace v1 gesturestart etc were named transformstart etc. There was wisdom in the naming. We probably should revert back to those event names. In addition, Wheelable takes care of mouse wheel gestures. The word gesture is way too generic.

axelpale commented 6 years ago

The previous proposition makes Touchable even more complex than it already is. The separation between transforms and taps in a nested structure would require careful and separate handling of both types of events, duplicating the tap threshold, distance, and T estimation logic. We want to keep things simple, KISS the sky, leading to the following advanced proposition.

Advanced proposition

axelpale commented 6 years ago

There is a big problem in the advanced proposition: N-finger tap does not have single position. For example four-finger tap on four separate tiles bubble to a mutual parent. Their mean point might even lay on an untouched item in the middle. In addition, the current API does not provide the points which is a usability feature: exact locations of fingers of a shaky hand should not have much power. Consider two fingers that touch the surface like pistons. Should the tap location be the position of the last finger or the first finger or the both? If the fingers move during the tap, should the position be at the start, end or somewhere between along the moved path? Or is this thinking just over-engineering? BOOM.

axelpale commented 6 years ago

Browsers solve the issue by throwing the ball to the programmer by providing the preventDefault method. We however cannot let programmer to prevent individual events because Touchable emits accumulated events, events that are result of multiple raw UIEvents.

However, we can provide similar via the mode as we previously tried to do with the propagate flag. But what keyword would replace propagate?

We choose preventDefault being the way to go because it is closest to the convention. To prevent major version increment, let it be true by default which is against the convention. Change the default value in v2.