前几天有给大家分享一个Vue自定义滚动条组件VScroll。今天再分享一个最新开发的React PC端模拟滚动条组件RScroll。
vue+pc桌面端模拟滚动条组件VScroll
rscroll 一款基于react.js构建的超小巧自定义桌面端美化滚动条。支持原生滚动条、自动隐藏、滚动条尺寸/层级/颜色等功能。
如上图:支持垂直/水平滚动条。
功能及效果和之前VScroll保持一致。在开发支持参考借鉴了el-scrollbar等组件设计思想。
调用非常简单,只需包裹住内容即可快速生成一个漂亮的滚动条。
引入组件
// 引入滚动条组件RScrollimport RScroll from './components/rscroll'
快速使用
这里是内容信息!这里是内容信息!这里是内容信息!
这里是内容信息!这里是内容信息!这里是内容信息!
这里是内容信息!这里是内容信息!这里是内容信息!
这里是内容信息!这里是内容信息!这里是内容信息!
编码实现
在components目录下新建rscroll目录,并创建index.js页面。
rscroll滚动条模板
render() { return (
this.$ref__box = el} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
this.$ref__wrap = el} onScroll={this.handleScroll}>
{prop.children}
{/* 滚动条 */}
this.$ref__barY = el} onMouseDown={this.handleDragThumb.bind(this, 0)} style={{background: prop.color, height: opt.barHeight+'px'}}>
this.$ref__barX = el} onMouseDown={this.handleDragThumb.bind(this, 1)} style={{background: prop.color, width: opt.barWidth+'px'}}>
)}
react监听元素/DOM尺寸变化。由于react不像vue可以自定义指令directives,只能使用componentDidUpdate来监听。
componentDidUpdate(preProps, preState) { // 监听内层view DOM尺寸变化 let $view = this.$ref__wrap.querySelector('.vscroll__view') const viewStyle = $view.currentStyle ? $view.currentStyle : document.defaultView.getComputedStyle($view, null); if(preState.$viewWidth !== viewStyle.width || preState.$viewHeight !== viewStyle.height) { this.setState({ $viewWidth: viewStyle.width, $viewHeight: viewStyle.height }) this.updated() }}
/** * ReactJs|Next.js自定义滚动条组件RScroll */import React from 'react'class RScroll extends React.Component { /** * 默认配置 */ static defaultProps = { // 是否显示原生滚动条 native: false, // 鼠标滑出是否自动隐藏滚动条 autohide: false, // 自定义滚动条大小 size: '', // 自定义滚动条颜色 color: '', // 滚动条层级 zIndex: null } constructor(props) { super(props) this.state = { barWidth: 0, // 滚动条宽度 barHeight: 0, // 滚动条高度 ratioX: 1, // 滚动条水平偏移率 ratioY: 1, // 滚动条垂直偏移率 isTaped: false, // 鼠标光标是否按住滚动条 isHover: false, // 鼠标光标是否悬停在滚动区 isShow: !this.props.autohide, // 是否显示滚动条 $viewWidth: null, $viewHeight: null, } } // 鼠标滑入 handleMouseEnter = () => { this.setState({ isHover: true, isShow: true }) this.updated() } // 鼠标滑出 handleMouseLeave = () => { const { isTaped } = this.state this.setState({ isHover: false }) this.setState({ isShow: false }) } // 拖动滚动条 handleDragThumb = (index, e) => { let _this = this this.setState({ isTaped: true }) const { ratioX, ratioY } = this.state let c = {} // 阻止默认事件 domUtils.isIE() ? (e.returnValue = false, e.cancelBubble = true) : (e.stopPropagation(), e.preventDefault()) document.onselectstart = () => false if(index == 0) { c.dragY = true c.clientY = e.clientY }else { c.dragX = true c.clientX = e.clientX } domUtils.on(document, 'mousemove', function(evt) { if(_this.state.isTaped) { if(c.dragY) { _this.$ref__wrap.scrollTop += (evt.clientY - c.clientY) * ratioY _this.$ref__barY.style.transform = `translateY(${_this.$ref__wrap.scrollTop / ratioY}px)` } if(c.dragX) { _this.$ref__wrap.scrollLeft += (evt.clientX - c.clientX) * ratioX _this.$ref__barX.style.transform = `translateX(${_this.$ref__wrap.scrollLeft / ratioX})` } } }) domUtils.on(document, 'mouseup', function() { _this.setState({ isTaped: false }) document.onmouseup = null document.onselectstart = null if(!_this.state.isHover && _this.props.autohide) { _this.setState({ isShow: false }) } }) } // 点击滚动槽 handleClickTrack = (index, e) => { // ... } // 更新滚动区 updated = () => { if(this.props.native) return let c = {} let barSize = domUtils.getScrollBarSize() // 垂直滚动条 if(this.$ref__wrap.scrollHeight > this.$ref__wrap.offsetHeight) { c.barHeight = this.$ref__box.offsetHeight **2 / this.$ref__wrap.scrollHeight c.ratioY = (this.$ref__wrap.scrollHeight - this.$ref__box.offsetHeight) / (this.$ref__box.offsetHeight - c.barHeight) this.$ref__barY.style.transform = `translateY(${this.$ref__wrap.scrollTop / c.ratioY}px)` // 隐藏系统滚动条 if(barSize) { this.$ref__wrap.style.marginRight = -barSize + 'px' } }else { c.barHeight = 0 this.$ref__barY.style.transform = '' this.$ref__wrap.style.marginRight = '' } // 水平滚动条 ... } // 鼠标滚动 handleScroll = (e) => { const { onScroll } = this.props typeof onScroll === 'function' && onScroll.call(this, e) this.updated() } render() { return ( // ... ) }}export default RScroll
这里是内容信息!这里是内容信息!这里是内容信息!
// 监听滚动事件handleScroll = (e) => { let _scrollTop = e.target.scrollTop let _scrollStatus // 判断滚动状态 if(e.target.scrollTop == 0) { _scrollStatus = '滚到至顶部' } else if(e.target.scrollTop + e.target.offsetHeight >= e.target.scrollHeight) { _scrollStatus = '滚动至底部' }else { _scrollStatus = '正滚动中..' } this.setState({ scrollTop: _scrollTop, scrollStatus: _scrollStatus })}
好了,以上就是基于react.js开发自定义美化滚动条组件。希望大家能喜欢~~