1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | 2x 6x 6x 6x 6x 6x 3x 3x 3x 1x 1x 3x 2x 3x 3x 3x 2x 1x 1x 1x 8x 8x 8x 3x 2x | import styles from './style.postcss'; import React, { PureComponent } from 'react'; import ReactIScroll from 'react-iscroll'; import iScroll from 'iscroll'; import classnames from 'classnames'; import is from 'is_js'; import PropTypes from 'prop-types'; const baseOptions = { deceleration: 0.01, bounce: false, scrollX: true, scrollY: false, scrollbars: true, interactiveScrollbars: true, eventPassthrough: true, keyBindings: true, mouseWheel: true, }; class HorizontalScroll extends PureComponent { constructor(props) { super(props); this.state = { isScrolling: false }; this._onBeforeScrollStart = this._onBeforeScrollStart.bind(this); this._onScrollCancelOrEnd = this._onScrollCancelOrEnd.bind(this); this._onScrollRefresh = this._onScrollRefresh.bind(this); } componentDidMount() { const { onScrollReady } = this.props; const isOnScrollReadySet = is.function(onScrollReady); if (isOnScrollReadySet) { this.hostNode.withIScroll(true, (scroll) => { isOnScrollReadySet && onScrollReady(scroll); }); } this._scrollToElement(); } componentDidUpdate(prevProps, prevState) { // if update was a user scroll don't do the auto scroll to element Eif (this.state.isScrolling !== prevState.isScrolling) return; this._scrollToElement(); } _scrollToElement() { const { scrollToElement } = this.props; const isScrollToElementSet = is.object(scrollToElement); if (isScrollToElementSet) { this.hostNode.withIScroll(true, (scroll) => { const { selector, duration, offsetX, offsetY, easing } = scrollToElement; scroll.scrollToElement( selector, duration, is.number(offsetX) ? offsetX : true, is.number(offsetY) ? offsetY : true, easing); }); } } _onBeforeScrollStart() { this.setState({ isScrolling: true }); } _onScrollCancelOrEnd() { this.setState({ isScrolling: false }); } _onScrollRefresh(_iScroll) { this.setState({ hasScroll: ! (_iScroll.x === _iScroll.maxScrollX && _iScroll.x === 0) }); } render() { const { className, innerClassName } = this.props; const iScrollClasses = classnames(styles.HorizontalScroll_iScroll, innerClassName, { [styles.__hasScroll]: !! this.state.hasScroll, [styles.__scrolling]: !! this.state.isScrolling, }); return <div className={classnames(styles.HorizontalScroll, className)}> <ReactIScroll className={iScrollClasses} iScroll={iScroll} options={baseOptions} ref={(node) => { this.hostNode = node; }} onBeforeScrollStart={this._onBeforeScrollStart} onScrollCancel={this._onScrollCancelOrEnd} onScrollEnd={this._onScrollCancelOrEnd} onRefresh={this._onScrollRefresh}> {this.props.children} </ReactIScroll> </div>; } } HorizontalScroll.propTypes = { className: PropTypes.string, innerClassName: PropTypes.string, children: PropTypes.node, onScrollReady: PropTypes.func, scrollToElement: PropTypes.shape({ selector: PropTypes.string.isRequired, duration: PropTypes.number, offsetX: PropTypes.number, offsetY: PropTypes.number, easing: PropTypes.object, }), }; export default HorizontalScroll; |