Skip to content

Instantly share code, notes, and snippets.

@fuermosi777
Last active December 23, 2015 12:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save fuermosi777/d46c539c2f0208143a1d to your computer and use it in GitHub Desktop.
Save fuermosi777/d46c539c2f0208143a1d to your computer and use it in GitHub Desktop.
React ScrollView Component

To use:

import ScrollView from 'ScrollView.jsx`;
...
render() {
    return (
    <ScrollView>
        {aListThatScrolls}
     </ScrollView>
    );
}
import React from 'react';
import Styles from './ScrollView.less';
export default React.createClass({
getInitialState() {
return {
height: 0,
handlerScrollTop: 0,
handlerHide: true
};
},
handlerHider: null,
scrollHandler: null,
lastPos: 0,
componentDidMount() {
window.addEventListener('resize', this.handleResize);
document.addEventListener('mousemove', this.handleHandlerMouseMove);
document.addEventListener('mouseup', this.handleHandlerMouseUp);
this.updateHeight();
},
componentWillUnmount() {
window.removeEventListener('resize', this.removeResize);
document.removeEventListener('mousemove', this.handleHandlerMouseMove);
document.removeEventListener('mouseup', this.handleHandlerMouseUp);
},
render() {
return (
<div className="ScrollView">
<div className="scrollbar">
<div className={"handler " + (this.state.handlerHide ? 'hide' : '')}
style={{height: '20%', top: this.state.handlerScrollTop.toString() + '%'}}
onMouseDown={this.handleHandlerMouseDown}/>
</div>
<div className="scroller" onScroll={this.handleScroll} ref="scroller">
{this.props.children}
</div>
</div>
);
},
handleScroll(e) {
clearTimeout(this.handlerHider);
let pos = e.target.scrollTop / (e.target.scrollHeight- this.state.height) * 0.8;
this.setState({
handlerScrollTop: pos * 100,
handlerHide: false
}, () => {
this.handlerHider = setTimeout(() => {
this.setState({handlerHide: true});
}, 1500);
});
if (pos < 0.2 && pos < this.lastPos && this.props.onApproachingTop) {
this.props.onApproachingTop();
}
if (pos > 0.6 && pos > this.lastPos && this.props.onApproachingBottom) {
this.props.onApproachingBottom();
}
this.lastPos = pos;
},
handleResize() {
this.updateHeight();
},
handleHandlerMouseDown(e) {
this.scrollHandler = e.target;
clearTimeout(this.handlerHider);
this.setState({handlerHide: false});
},
handleHandlerMouseMove(e) {
if (this.scrollHandler) {
let pos = (e.pageY) / this.state.height;
pos = (pos < 0 ? 0 : (pos > 0.8 ? 0.8 : pos)) * 100;
React.findDOMNode(this.refs.scroller).scrollTop = pos * React.findDOMNode(this.refs.scroller).scrollHeight / 100;
}
},
handleHandlerMouseUp(e) {
this.scrollHandler = null;
clearTimeout(this.handlerHider);
this.handlerHider = setTimeout(() => {
this.setState({handlerHide: true});
}, 1500);
},
updateHeight() {
this.setState({height: React.findDOMNode(this).offsetHeight});
}
});
@import (reference) "../Base/Base.less";
.ScrollView {
overflow: hidden;
height: 100%;
position: relative;
.scrollbar {
position: absolute;
width: 8px;
top: 0;
right: 0;
height: 100%;
.handler {
background-color: rgba(0, 0, 0, 0.5);
position: absolute;
width: 6px;
left: 1px;
border-radius: 3px;
z-index: 1;
.transition(@time: 0.2s, @type: background-color);
&.hide {
background-color: rgba(0, 0, 0, 0);
}
&:hover {
background-color: rgba(0, 0, 0, 0.7);
}
&:active,
&:focus {
cursor: default;
}
}
}
.scroller {
overflow-y: auto;
height: 100%;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: -20px;
padding-right: 20px;
}
}
@yangsibai
Copy link

非常好用。
我都已经打算自己写了才发现你的组件,初步使用下来就感觉很棒了。谢谢。
目前感觉滚动时有一点生涩感,我自己再改进一下。
已经节省了我很多时间,再次感谢。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment