Open uncvrd opened 4 years ago
Thanks for the issue. Can you clarify the issue you are running into? You should be able to check index === 0 && ev.deltaX > 0
in onMove
, and then do nothing if that case returns true.
Hey @liamdebeasi ! So the issue I have with short circuiting within the onMove
event is that this will still result in an onEnd
event firing if index === 0 && ev.deltaX > 0
. This causes an issue because, I have the following onEnd
method which disables the gesture until an animation completes:
const onEnd = (ev: GestureDetail) => {
swipeGesture.enable(false);
// if velocity is large enough, automatically translate to next story
if (Math.abs(ev.velocityX) > 0.12) {
onChange(ev.deltaX < 0 ? index + 1 : index - 1);
return;
}
// next
if (ev.deltaX < -(width / 2)) {
onChange(index + 1);
// prev
} else if (ev.deltaX > width / 2) {
onChange(index - 1);
// current
} else {
set({
rotateY: index * 90 * -1,
onRest: () => {
// re-enable gesture
swipeGesture.enable(true);
setAnimating(false);
},
immediate: false,
});
}
};
As you can see, i have a swipeGesture.enable(false)
at the top of my onEnd
method so that I can allow the animation to finish before allowing the swipeGesture
to listen for more gesture events again. Since there is no animation that is completing (because we are short circuiting with no movement), the swipeGesture
can never be re-enabled. I took this concept from the example in the docs here: https://ionicframework.com/docs/utilities/animations#gesture-animations
Here's the code snippet I'm referring to, notice how gesture
is disabled until onFinish
? That's what I'm doing with my onEnd
as well:
const onEnd = (ev): {
if (!started) { return; }
gesture.enable(false);
const step = getStep(ev);
const shouldComplete = step > 0.5;
animation
.progressEnd((shouldComplete) ? 1 : 0, step)
.onFinish((): { gesture.enable(true); });
initialStep = (shouldComplete) ? MAX_TRANSLATE : 0;
started = false;
}
So to clarify, short circuiting in the onMove
still causes an onEnd
event to fire even though there is no animation translation happening. In the onEnd
, the swipeGesture
is disabled until the animation complete, but since we are hitting the onEnd
event with no translation, the swipeGesture
will no be re-enabled
Does that help a bit? Thanks!
Hmm can you make a CodePen/GitHub repo with what you are trying to do? It's hard to get a good idea of what is going on without being able to interact with the gesture.
edit: If you put the code into an Ionic starter app and push it to GitHub that might be fastest.
@liamdebeasi here's a sample repo!
Link: https://github.com/uncvrd/ionic-gesture-direction
The Home.tsx has the demo.
Cube.tsx is where most of the inner workings are. I initialize and use Ionic Gestures on line 137 of Cube.tsx
.
In the demo, if you try swiping back on the first slide it will not change since we are shortcircuiting the animation in onMove
(great!), however the swipeGesture
will be disabled due to the fact that once you let go of the gesture, onEnd
is fired. Normally, this gesture is re-enabled on the completion of an animation, but since we are shortcircuiting in onMove
and preventing any animation, the animation finish callback never fires since there is no animation to "complete" (which reenables the gesture as you can see on line 185).
Let me know if you have more questions
Thanks for the repo. So I was able to get this gesture to work by adding the following to the top of onEnd
:
if (index === 0 && ev.deltaX > 0) {
return;
}
Can you try this and let me know if it resolves the issue?
@liamdebeasi yes this will suffice as a work around, thanks! What are your thoughts about keeping this open as a feature request? My reasoning being:
onMove
to prevent panning back if index == 0onMove
to prevent panning forward if index == images.length (reached the end)onEnd
to prevent events from firing if index == 0onEnd
to prevent events from firing if index == images.lengthI think it would be a nice extension to the gesture controller to be able to control which specific magnitude of direction a gesture can handle. Just a thought!
HammerJS exposes a direction
property on each event object -- I think we could do something like that. In your app, you would just check event.direction === 'left'
or something similar.
@liamdebeasi I think that would be useful! Or an event exposed that we can use to be able to check and prevent the animation from even starting. For example react-gesture-responder
allows you to listen for a gesture event, check direction, and prevent movement (sort of like canStart
in Ionic Gestures, but this one you can actually detect direction). For example:
onMoveShouldSet: ({ direction }) => {
if (!enableGestures) {
return false;
}
// beginning of stack and swiping left
if (index === 0 && direction[0] > 0) {
return false;
}
// end of stack and swiping right
if (direction[0] < 0 && !hasNext(index)) {
return false;
}
// swiping horizontally
return Math.abs(direction[0]) > Math.abs(direction[1]);
},
Maybe this can be fixed with adding direction
to the GestureDetail
for canStart
, but it seems like it triggers RIGHT on click/press so I don't know if it can detect direction.
Link to repo: https://github.com/bmcmahen/react-gesture-responder
Note: this is what I was using before switching to Ionic Gestures. I switched because I was having conflicting gesture priorities with Ionics SwipeToClose Modal gesture. Switched so I can manage gesture priorities in a single gesture library :)
I'm guessing this has been forgotten about but in case someone from Ionic sees this, I'm running into similar issues as the other posters.
I have multiple swipes on the screen that can potentially block each other.
If the canStart
was triggered after the threshold got crossed then it would be possible to return false when a swipe is left to right. Then it wouldn't block a right to left swipe.
Feature Request
Hi! I have a specific use case where I have an instagram stories-esque image carousel in my app. I am using Ionic Gestures to listen for pan events when swiping to the next image. The issue I have is that I am unable to disable a swipe gesture in a specific direction on the x axis.
For example, when the user opens their stories, they should not be able to swipe backwards because they are watching their first story. I figured I could use the
canStart
event for this. However, theGestureDetail
'sdeltaX
value is 0 since it is triggered right at the beginning of the gesture event (e.g. no delta has been registered).I was wondering if we could have some sort of API that would allow us to prevent gestures in a negative of positive direction on an axis? Or is there a better way to do what I'm explaining?
Notice the black screen when I try to swipe back? I am at index 0 and should not be allowed to swipe back like that.
For example here's my React Gesture:
I use
react-spring
for my transition animations:In my code I can check to see if the user is at
index === 0
, if so, I would like to prevent pan gestures that result in a positivedeltaX
event.Describe Preferred Solution
A very rough idea is to have an API like:
axis: 'positive' | 'negative' | 'both'
If it was possible to use
canStart
for this, I would do something like:Describe Alternatives
I've tried to
swipeGesture.enable(false)
within myonMove()
method with hopes that anonEnd()
event would be called, so that I could re-enable the gesture once they let go but that doesn't work either.Any thoughts on this would be super helpful, thank you!
Ionic version:
[x] 5.1.0