Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for wheel event scrolling #47

Closed
sphair opened this issue Feb 21, 2020 · 30 comments
Closed

Add support for wheel event scrolling #47

sphair opened this issue Feb 21, 2020 · 30 comments
Labels
feature request New feature or request resolved This issue is resolved

Comments

@sphair
Copy link

sphair commented Feb 21, 2020

When using touchpad on an MacBook, you can use two-finger gestures for scrolling. As far as I understand, these values are available through "wheel" events in javascript.

It would be very nice to have support for horizontal scrolling using touchpad in Embla Carousel if possible.

Here is a fiddle that demonstrates the values received: https://jsfiddle.net/64p5r459/2/

@davidjerleke davidjerleke added the feature request New feature or request label Feb 21, 2020
@davidjerleke
Copy link
Owner

davidjerleke commented Feb 21, 2020

Hi Kenneth (@sphair),

Thank you for your feature request. That’s correct, the two-finger gesture on a touchpad triggers the JavaScript wheel event. Additionally, a mouse with a wheel also triggers the wheel event.

Do you mind if I change the title of this issue to:

Add support for wheel event scrolling?

To cover all devices with wheels?

Kindly,
David

@sphair sphair changed the title Support touchpad scrolling through two-finger gesture Add support for wheel event scrolling Feb 21, 2020
@remisture
Copy link

I need this as well 👍

@horgen
Copy link

horgen commented Mar 6, 2020

Any idea when you will be able to start on this? I need this before I can use embla in production.

@davidjerleke
Copy link
Owner

davidjerleke commented Mar 6, 2020

Hi @horgen, thank you for your question.

Short answer

Unfortunately, no.

Long answer

I have a huge backlog including everything from a lot of feature requests to writing documentation, troubleshooting (see issue #45 and #12) and setting up CodeSandbox demonstrations etc.

Additionally, I've lately had a lot of demonstration issues which aren't necessarily related to Embla but rather JavaScript skills (and React knowledge for the React package) 👇.

demonstration

This product is an open source product and I'm hoping for the community to help me out with stuff like this so I can spend more time on new features and code quality. But unfortunately, contributions are really rare, so things are progressing slow.

With that said, I'm doing my best and I'm hoping to be able to investigate this soon, but can't give you an estimate on when this will happen. I hope you understand.

Best,
David

@yunusabd
Copy link

yunusabd commented Apr 12, 2020

Here's my solution. I'm using a throttling function to adjust for the sensitivity of trackpads. Otherwise the carousel will just fly past at the slightest touch.

function throttled(delay, fn) {
    let lastCall = 0;
    return function(...args) {
        const now = new Date().getTime();
        if (now - lastCall < delay) {
            return;
        }
        lastCall = now;
        return fn(...args);
    };
}

window.addEventListener(
    "wheel",
    throttled(350, e => {
        if (e.deltaY > 0) this.embla.scrollNext();
        else this.embla.scrollPrev();
    })
);

@xiel
Copy link
Contributor

xiel commented May 11, 2020

Hey David (@davidcetinkaya),

maybe we continue our discussion here. Working with the engine worked great!
Here is the result so far: https://embla-carousel-wheel-gestures-7ejp8ofex.now.sh

I think it feels pretty nice, I tested with a Macbook Pro and a Surface Laptop (in all modern browsers). Hope it works fine on your device too ;)

CodeSandbox can't install from git repositories yet, so I put the code here.

Just the out-of-bounds/bouncing off the edges (when loop: false) does not look quite right yet. Maybe you know a better way to set the values? So it does not start to animate back on its own?

Also I think to have a fully reliable add-on a reInit/updated event would be great too, in case the containerNode (or other things change). Also a way to read the options from the engine would be helpful, in this case the dragFree option would be of interest.

Cheers!
– Felix

@davidjerleke
Copy link
Owner

davidjerleke commented May 11, 2020

Hi Felix (@xiel),

Nicely done! Looking good 🙂.

I think it makes a lot of sense to expose the options with the engine method embla.dangerouslyGetEngine() of course. I'll fix that as soon as possible.

The reInit method is actually available in the latest pushed commit (not release!). It will be released with Embla v.3 (as mentioned earlier I'm working on v.3 right now).

embla.changeOptions(options)

// has been renamed to 

embla.reInit(options)

...where the options object is optional.

The out-of-bounds/bouncing you mention is done automatically if the animation loop is going in the scrollBounds.ts component. Please take a look at this line of code. I'm thinking if you update the Embla target as the wheel is scrolling you can stop doing so when it's out of bounds. That check can be made like so:

const engine = embla.dangerouslyGetEngine()
const reachedAnyBound = engine.limit.reachedAny(engine.location.get())

if (reachedAnyBound) {
  // Don't trigger more scroll
}

Now I haven't tested this with your implementation so forgive me if it's a dead end 😉. Let me know if it helps.

Best,
David

@davidjerleke
Copy link
Owner

Hello again Felix (@xiel),

The options object is now exposed when you grab the engine. It comes with this commit.

Cheers,
David

@xiel
Copy link
Contributor

xiel commented May 13, 2020

@davidcetinkaya Awesome!

Do you think you can also trigger a "reInit" or "activate" in when it is not isFirstInit here?https://github.com/davidcetinkaya/embla-carousel/blob/bd08fe6c6cab99fcde6faca454f1de7a296a3f01/src/index.ts#L69

Because I would also need to re-init the plugin, when the user updates the option for axis for example, or when the containerNode changed etc.

embla.on("activate", reInitWheelPlugin)

And I'm still having a problem with targets out of bounds.
While you can drag the carousel with the mouse out-of-bounds, as long as you don't lift, it does not move the carousel back into the bounds.

But when I update the target via target.add it always tries to snap back into the bounds, which makes the carousel stutter/shake.

Here is a simple demo showing it, by just continously moving right:
https://embla-carousel-wheel-gestures-chkfijdlk.now.sh
I would expect that it moves the content out of the viewport in this simple example.

It there a way to disable the bounds temporarily, which I did not find yet? :)

const emblaEngine = embla.dangerouslyGetEngine();

embla.on("init", () => {
  emblaEngine.scrollBody.useDefaultMass().useSpeed(80);
  moveRight();
});

function moveRight() {
  const reachedAnyBound = emblaEngine.limit.reachedAny(
    emblaEngine.location.get()
  );
  emblaEngine.animation.start();
  emblaEngine.target.add(-10 / (reachedAnyBound ? 2 : 1));
  requestAnimationFrame(moveRight);
}

@davidjerleke
Copy link
Owner

Hello Felix (@xiel),

Of course, exposing the:

embla.on("reInit", callback)

...event makes sense.

Now I understand the out of bounds issue you’re experiencing. Hmm. This one is a bit tricky. One way to do it would be to not use any out-of-bounds-effect. So basically never let the target exceed any of the bounds when scrolling the wheel. Because otherwise I’m thinking that it can get quite messy exposing a lot of stuff unless the wheel behavior is actually built into the Embla core 😕.

What do you think?

Kindly
David

@xiel
Copy link
Contributor

xiel commented May 15, 2020

@davidcetinkaya Yea, that's fine! Definitely good enough for a first version 💯

no out-of-bounds: https://embla-carousel-wheel-gestures-hio0j134f.now.sh
shaky out-of-bounds https://embla-carousel-wheel-gestures-nh59111ur.now.sh

I think it feels better with the shaky version, than no out-of-bounds at all, because it feels too different to native behaviour on Mac imho.

Also when the carousel is directly at one of the bounds, it still returns false, which makes it behave weirdly sometimes when I disallow out-of-bounds.

Looking forward to the reinit event ;) Thanks for working on this!

@davidjerleke
Copy link
Owner

@xiel, I'll see if it's possible to add the disable bounds method soon. About the reInit event, maybe it should trigger on resize too? Because Embla re-initialises on resize.

@xiel
Copy link
Contributor

xiel commented May 18, 2020

yes, that sounds reasonable, no matter what the reason is embla reInits, it would be good to know ;)

@davidjerleke
Copy link
Owner

davidjerleke commented May 18, 2020

Allright @xiel 🙂,

If you grab the latest commit you have the reInit event ready to go 😉. So you probably don't have to listen to the resize event at all, because the reInit event fires in these cases too.

I'll let you know how it goes with disabling the scrollBounds.

Cheers!

@davidjerleke
Copy link
Owner

davidjerleke commented Jun 6, 2020

Hi Felix (@xiel),

The latest commit comes with the possibility to toggle the scrollBounds active/inactive 🙂:

emblaEngine.scrollBounds.toggleActive(false) // disable

// ...or

emblaEngine.scrollBounds.toggleActive(true) // enable

Note that they're enabled by default for non loop carousels. Let me know if it works as intended.

Best,
David

@xiel
Copy link
Contributor

xiel commented Jun 6, 2020

@davidcetinkaya Awesome, I will have a look this weekend. Thanks!

@xiel
Copy link
Contributor

xiel commented Jun 8, 2020

Hey David (@davidcetinkaya),

reinit and bounds de/activating work perfectly and create a really great UX now! 🥳

Here is the updated version: https://embla-carousel-wheel-gestures-jsulrk1a3.now.sh (Code)

Thanks for the additional API, looking forward to the release of 3.0!
– Felix

@davidjerleke
Copy link
Owner

Hey Felix (@xiel), nice work 🎉 !

Looking good to me! I'm glad the additions helped you achieve this 🙂. Version 3 is just around the corner now. I'm very excited about the release, even though it means a lot of work rewriting the documentation, and not to mention merging all option demonstration CodeSandboxes into one, where you're going to be able to toggle all the different options.

So are you wrapping up the wheel package or what's your plan from here 🙂?

@xiel
Copy link
Contributor

xiel commented Jun 9, 2020

@davidcetinkaya Haha, yea writing all the documentation and demos is often the even harder work. 😅

Yes, my plan would be to wrap this into a small npm package during the coming days. I will also ensure this works great with the react version of embla. I will add you to the repository then, if that is ok? In case you need to make breaking changes in the future or so :) But no pressure, I will try to keep it up-to-date.

To set things up more easily, it would help me, if embla 3.0 was pre-released with a next/beta dist tag on npm, because some tools don't allow to install from git and require local linking. Would you consider doing that? (Might also help you, to setup and test new CodeSandboxes).

I'll keep you posted, I hope to be ready soon after 3.0 is ready! :)

@davidjerleke
Copy link
Owner

davidjerleke commented Jun 10, 2020

Hello again Felix (@xiel),

Next up is the release of v.3 so I think doing a pre-release will rather slow things down at this point. There's no turning back 😂 . Of course, add me to the repo 🙂.

I'll let you know when v.3 is out!

Kindly,
David

@xiel
Copy link
Contributor

xiel commented Jun 10, 2020

alrighty, i’ll just wait for the release 👍

@davidjerleke
Copy link
Owner

Hello Felix (@xiel),

Version 3 is out 📣! Please read more about it here. I will update the documentation as soon as possible.

Enjoy 😊!
David

@xiel
Copy link
Contributor

xiel commented Jun 15, 2020

Here we go, the wheel events plugin is out as well 🥳

Installation & Examples

yarn add embla-carousel-wheel-gestures # npm install --save embla-carousel-wheel-gestures
import EmblaCarousel from 'embla-carousel'
import { setupWheelGestures } from 'embla-carousel-wheel-gestures'

// initialize Embla Carousel
const embla = EmblaCarousel(emblaNode, options)

// add support for wheen events
setupWheelGestures(embla)

Thanks for providing the nessessary API, @davidcetinkaya !

@davidjerleke
Copy link
Owner

Hello Felix (@xiel),

Wow, awesome work 🎉 🥳!
Thank you for your efforts and I'm going to try it out a bit in the next few days. Really straightforward documentation so nicely done 🙂.

@sphair, @remisture and @horgen, this solves your feature request right?

Best,
David

@davidjerleke
Copy link
Owner

davidjerleke commented Jun 16, 2020

@xiel I'm going to add this to the readme just to let users know it's there 🙂. Do you have any suggestions where it should be added?

If you want to add the Embla logo to the documentation page, that's totally ok. But don't feel obligated to. Only add it if you think it makes sense.

(If you have a better suggestion for a better looking logo, please share it 😜. This is kind of a joke, but also not 😂.)

@xiel
Copy link
Contributor

xiel commented Jun 16, 2020

@davidcetinkaya Hehe, good question. Maybe below the CodeSandboxes as a new section "Plugins" or "Add-ons"?

Cool, I thought about adding the Logo, but wanted you permission first 👍

@davidjerleke
Copy link
Owner

@xiel this is totally unrelated but take a look at this CodeSandbox. Was just fooling around a bit 🙂.

@xiel
Copy link
Contributor

xiel commented Jun 22, 2020

@davidcetinkaya wow really cool! perfect demo for the y axis!

@davidjerleke
Copy link
Owner

Closing this as resolved. Thank you Felix (@xiel) for your efforts 👍.

@davidjerleke
Copy link
Owner

davidjerleke commented Jun 27, 2020

Hello Felix (@xiel),

In order to get rid of maintaining two separate repos I've merged embla-carousel-react into the core library. This was finalized in v3.0.15. I thought it would be good to mention it because the wheel gesture package is dependent on this 🙂. I'm hoping that this won't cause too much trouble for you.

@davidjerleke davidjerleke added the resolved This issue is resolved label Jul 14, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request New feature or request resolved This issue is resolved
Projects
None yet
Development

No branches or pull requests

6 participants