Last active
October 20, 2022 03:50
-
-
Save clauderic/13cc9207a9e5db63ee67a1588eb11811 to your computer and use it in GitHub Desktop.
Smooth scrolling to a given offset in React Virtualized
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Smoothly animate between two values | |
| * @param {Number} fromValue - the initial value | |
| * @param {Function} onUpdate - A function that is called on each tick | |
| * @param {Function} onComplete - A callback that is fired once the scroll animation ends | |
| * @param {Number} duration - the desired duration of the scroll animation | |
| */ | |
| export default function animate({ | |
| fromValue, | |
| toValue, | |
| onUpdate, | |
| onComplete, | |
| duration = 600, | |
| }) { | |
| const startTime = performance.now(); | |
| const tick = () => { | |
| const elapsed = performance.now() - startTime; | |
| window.requestAnimationFrame(() => onUpdate( | |
| getValue(fromValue, toValue, elapsed, duration), | |
| // Callback | |
| elapsed <= duration | |
| ? tick | |
| : onComplete | |
| )); | |
| }; | |
| tick(); | |
| }; | |
| /** | |
| * Given a start/end point of a scroll and time elapsed, calculate the scroll position we should be at | |
| * @param {Number} start - the initial value | |
| * @param {Number} stop - the final desired value | |
| * @param {Number} elapsed - the amount of time elapsed since we started animating | |
| * @param {Number} - duration - the duration of the animation | |
| * @return {Number} - The value we should use on the next tick | |
| */ | |
| function getValue(start, end, elapsed, duration) { | |
| if (elapsed > duration) return end; | |
| return start + (end - start) * easing(elapsed / duration); | |
| }; | |
| // For this example, I've used easeOutQuart, see https://gist.github.com/gre/1650294 for different easings | |
| function easing(time) { | |
| return 1 - (--time) * time * time * time; | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import React, {Component} from 'react'; | |
| import {List} from 'react-virtualized'; | |
| import animate from './animate'; | |
| class App extends Component { | |
| state = { | |
| scrollTop: 0, | |
| } | |
| handleScroll = ({scrollTop}) => { | |
| // Store the current scroll offset | |
| this.scrollTop = scrollTop; | |
| } | |
| scrollTo(offset) { | |
| animate({ | |
| fromValue: this.scrollTop, | |
| toValue: offset, | |
| onUpdate: (scrollTop, callback) => this.setState({scrollTop}, callback), | |
| onComplete: () => console.log('Scroll animation complete!'), | |
| }); | |
| } | |
| rowRenderer = ({index, key, style}) => { | |
| return ( | |
| <div key={key} style={style}> | |
| Row #${index} | |
| </div> | |
| ); | |
| } | |
| render() { | |
| const {scrollTop} = this.state; | |
| return ( | |
| <List | |
| width={300} | |
| height={300} | |
| rowCount={500} | |
| rowHeight={20} | |
| rowRenderer={this.rowRenderer} | |
| scrollTop={scrollTop} | |
| onScroll={this.handleScroll} | |
| /> | |
| ); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment