davidjerleke / embla-carousel

A lightweight carousel library with fluid motion and great swipe precision.
https://www.embla-carousel.com
MIT License
5.91k stars 178 forks source link

Scroll Progress (get) #21

Closed davidjerleke closed 4 years ago

davidjerleke commented 5 years ago

πŸ‘‰ Conclusion / Feature Specification

The discussion in this issue has resulted in a decision to implement the following API method:

// get scroll progress
// returns a number representing % scrolled of scrollable distance.
// 0 is start position and 1 is end position

embla.scrollProgress()

Example Usage

embla.on('scroll', () => {
  console.log(`Current progress is: ${embla.scrollProgress() * 100}%`)
}

CodeSandbox

See example usage.

Special thanks

@xiel for discussing this and sharing your thoughts and ideas. @welteki for the nice demonstration.

xiel commented 5 years ago

Hey David, I think this makes a lot of sense and would be a great addition to the API. It would make it possible to sync other things to the movement or implement other kinds of pagination indicators etc.

Would you also consider an API for setting of scroll progress at the same time? embla.scrollProgress(20) embla.scrollBy(-15)

This could be used to sync Embla to external things (like scroll position in one-pagers or other kinds of user input).

Cheers!

davidjerleke commented 5 years ago

Hi Felix (@xiel), Thank you for your feedback. This is a great suggestion πŸ™‚.

Just want to confirm that I understand you correctly. At the time of writing we have a method called: embla.scrollTo(index) which scrolls to a specific snap point index. Maybe we should think about how we name these methods to avoid confusion?

Is this what you had in mind?

Best, David

xiel commented 5 years ago

I had a get/set interface in mind, so when you do not pass anything, you get the current value back. And if you pass something, this value will gets applied.

embla.scrollProgress() // get in % embla.scrollProgress(number) // set in %

Sometimes relative change to the current position is more interesting. For that, a second convenience method could offer to update the position by a relative value (similar to window.scrollBy):

embla.scrollBy(0.25) // change current by % (default, to be analog to the unit of scrollProgress) embla.scrollBy(340, 'px') // change based on current +/- using px

I think it makes sense to also allow setting and getting in px dimensions, this could be done either as a second parameter (px / %) or side-by-side as own methods?

Recarding the unit, I would also suggest to use 0..1 range for percentage (instead of 1..100), as it is more common in JS and easier to distinguish from px values.

Sorry for all the requests. Happy to take this into a separate issue if it's to much here ;)

davidjerleke commented 5 years ago

Hello Felix (@xiel),

That's surely a lot to take in πŸ˜„. But I always appreciate ideas so thank you for taking time to discuss this. So I think embla.scrollProgress() is pretty straightforward:

embla.scrollProgress()
// get scroll progress
// returns a number from 0 - 1 representing % scrolled of scrollable distance

And I think I understand the idea for scrollProgress(number) and scrollBy(number):

embla.scrollProgress(0.5)
// set scroll progress
// accepts a number from 0 - 1 representing % scrolled of scrollable distance
embla.scrollBy(0.5)
// set scroll position relative to current
// accepts a number from 0 - 1 representing % to scroll based on current scroll position

Methods like scrollProgress(number) and scrollBy(number) would move the carousel to arbitrary positions (not a snap point), pretty much like when you drag the carousel and have { dragFree: true }. Maybe I'm missing something obvious, but do you have use case/cases in mind for this to help me understand this better when these methods could be useful?

Regarding px units I think it's a bigger surgical intervention because at the time of writing Embla translates the carousel with % rather than px. So maybe it makes sense to open a separate issue for the px request πŸ˜‰.

Best David

welteki commented 4 years ago

Hi David (@davidjerleke),

A couple of months ago I forked this repository with a similar idea in mind. I wanted to create a carousel with parallax effect and changing background gradient but in order to do this I needed the scroll progress. I made a quick implementation to experiment with this a bit.

Here's an example: https://codesandbox.io/embed/embla-carousel-scroll-event-czzbo My implementation isn't great but I hope this can give you an idea of how this API can be used.

xiel commented 4 years ago

Hey @davidjerleke,

use cases for setting the scroll position manually:

I think it does not make sense to implement all these use cases within Embla itself, but I would love to see the API evolve and being able to implement them myself when needed. And a way to change the scroll position would definitely be needed for that.

I agree that the developer might move the carousel to arbitrary positions, that should be a solvable challenge. Could the developer not just call scrollTo(selectedScrollSnap()) to make it snap if wanted?

I have not dived deep into the code, but don't you already map from px dimensions to % dimensions in your drag implementation? Otherwise providing the scroll length would also be sufficient, then the developer could map to percentage values himself.

Best, Felix

davidjerleke commented 4 years ago

Hello Han (@welteki),

Very creative with the background color changing, I like it πŸ˜„. And thank you for this example, I think it's a great demonstration for other users browsing this issue. This feature will be implemented as soon as possible. Do you have any further ideas about this feature that you think could be valuable?

Best, David

davidjerleke commented 4 years ago

Hi @xiel,

Thank you for taking time to explain πŸ’ͺ.

I agree that the developer might move the carousel to arbitrary positions, that should be a solvable challenge. Could the developer not just call scrollTo(selectedScrollSnap()) to make it snap if wanted?

You're absolutely right about this.

I've decided to split all feature requests in this discussion into separate issues. I think it will make it easier to follow each feature request and implement them separately, one by one. I hope this is ok with you.

Please see ScrollBy #23.

Best, David

davidjerleke commented 4 years ago

Hi Felix (@xiel),

About the method for setting scroll progress embla.scrollProgress(number), we are talking about an instant setter right? Meaning using this method won’t scroll to desired position but rather go there instantly. I’d like to hear your thoughts.

Thank you for your attention! David

xiel commented 4 years ago

Yes, I would expect it to be an instant setter by default.

davidjerleke commented 4 years ago

Hello @xiel and @welteki,

I'm happy to announce that the first part of this, the scroll progress getter has been released with version 2.5.0 πŸš€.

Read more here or check this CodeSandbox out.

Enjoy!