UNPKG

pretty-scrollbar

Version:

pretty your scrollbar

231 lines (198 loc) 7.67 kB
/* * Project: pretty-scrollbar * Author: PengJiyuan * Create: 2016/11/18 * Update: 2016/11/23 * */ function prettyScroll(element, options) { this.defaultOptions = { defaultWrapperWidth: 20, barWidth: 7, wrapperColor: null, barColor: 'rgba(0, 0, 0, 0.4)', right: 2, autoHide: true }; this.config = Object.prototype.toString.call(options) === '[object Object]' ? Object.assign(this.defaultOptions, options) : this.defaultOptions; this.ele = document.querySelector(element); //target element this.hasCreated = false; } prettyScroll.prototype = { getStyle: function (selector) { return selector.currentStyle ? selector.currentStyle : document.defaultView.getComputedStyle(selector, null); }, bind: function(target, eventType, handler) { if (window.addEventListener) { target.addEventListener(eventType, handler, false); } else if (target.attachEvent) { target.attachEvent('on' + eventType, handler); } else { target['on' + eventType] = handler; } return target; }, unbind: function(target, eventType, handler) { if (window.removeEventListener) { target.removeEventListener(eventType, handler, false); } else if (window.detachEvent) { target.detachEvent(eventType, handler); } else { target['on' + eventType] = ''; } }, createProps: function() { this.height = parseInt(this.getStyle(this.ele).height); //target's height this.scrollHeight = this.ele.scrollHeight; //target's true height if(this.height < this.scrollHeight) { this.ele.style.boxSizing = 'border-box'; } this.width = parseInt(this.getStyle(this.ele).width); //target's width this.x = this.ele.getBoundingClientRect().left + document.body.scrollLeft; //target's x this.y = this.ele.getBoundingClientRect().top + document.body.scrollTop; //target's y this.defaultBgColor = this.getStyle(this.ele).backgroundColor; if(this.config.wrapperColor) { this.bgcolor = this.config.wrapperColor; } else { this.bgcolor = /^rgb/.test(this.defaultBgColor) && this.defaultBgColor !== 'rgba(0, 0, 0, 0)' ? this.getStyle(this.ele).backgroundColor : '#fff'; } this.barHeight = this.height*this.height/this.scrollHeight; this.wrapperStyle = 'position: absolute;top: '+this.y+'px;left: '+(this.x+this.width-this.config.defaultWrapperWidth) +'px;width: '+this.config.defaultWrapperWidth+'px;height: '+this.height +'px;background-color: '+this.bgcolor+';z-index:10'; this.barStyle = 'position: absolute;z-index: 9;width: '+this.config.barWidth +'px;height: '+this.barHeight+'px;top: 0;right: '+this.config.right +'px;background-color: '+this.config.barColor+';border-radius: ' +this.config.barWidth+'px;'+(this.config.autoHide ? 'opacity: 0;transition: opacity 0.4s' : ''); }, initScrollBar: function() { this.initResize(); this.initBar(); }, initResize: function() { this.createEvents(); this.bind(window, 'resize', this.events.resize); }, initBar: function() { this.createProps(); if(this.height < this.scrollHeight) { this.hasCreated = true; this.bar = document.createElement('div'); // create bar this.bar.style = this.barStyle; this.barWrapper = document.createElement('div'); // create wrapper this.barWrapper.style = this.wrapperStyle; this.barWrapper.appendChild(this.bar); document.body.appendChild(this.barWrapper); this.initEventScroll(); } }, initEventScroll: function() { this.bind(this.ele, 'scroll', this.events.scroll); this.bind(this.bar, 'mousedown', this.events.down); if(this.config.autoHide) { this.initEnter(); } }, // mouseenter the target and show the scrollbar initEnter: function() { this.bind(this.ele, 'mouseenter', this.events.enter); this.bind(this.ele, 'mouseleave', this.events.leave); this.bind(this.barWrapper, 'mouseenter', this.events.enter); this.bind(this.barWrapper, 'mouseleave', this.events.leave); }, removeEnter: function() { this.unbind(this.ele, 'mouseenter', this.events.enter); this.unbind(this.ele, 'mouseleave', this.events.leave); this.unbind(this.barWrapper, 'mouseenter', this.events.enter); this.unbind(this.barWrapper, 'mouseleave', this.events.leave); }, removeScrollBar: function() { this.hasCreated = false; document.body.removeChild(this.barWrapper); this.unbind(this.ele, 'scroll', this.events.scroll); this.unbind(this.bar, 'mousedown', this.events.down); this.unbind(document, 'mouseup', this.events.up); this.unbind(document, 'mousemove', this.events.move); if(this.config.autoHide) { this.removeEnter(); } }, createEvents: function() { this.events = { resize: (function(_this) { return function(e) { if(!_this.hasCreated) { _this.initBar(); } else { _this.createProps(); if(_this.height < _this.scrollHeight) { _this.bar.style.height = _this.height*_this.height/_this.scrollHeight + 'px'; _this.barWrapper.style.height = _this.height + 'px'; _this.barWrapper.style.top = _this.y + 'px'; _this.barWrapper.style.left = _this.x + _this.width - _this.config.defaultWrapperWidth + 'px'; } else { _this.removeScrollBar(); } } }; })(this), scroll: (function(_this) { return function(e) { var intervalTargetHeight = _this.scrollHeight - _this.height; var intervalBarHeight = _this.height - _this.barHeight; var go = _this.ele.scrollTop/intervalTargetHeight*intervalBarHeight; _this.bar.style.top = go+'px'; return false; }; })(this), down: (function(_this) { return function(e) { _this.pY = e.pageY; _this.cacheTop = parseInt(_this.bar.style.top); _this.bind(document, 'mouseup', _this.events.up); _this.bind(document, 'mousemove', _this.events.move); }; })(this), up: (function(_this) { return function(e) { _this.unbind(document, 'mousemove', _this.events.move); _this.unbind(document, 'mouseup', _this.events.up); }; })(this), move: (function(_this) { return function(e) { var cap = e.pageY - _this.pY; if(parseInt(_this.bar.style.top) <= 0 && cap < 0) { _this.pY = e.pageY; _this.bar.style.top = 0; _this.cacheTop = 0; return; } if(parseInt(_this.bar.style.top) >= parseInt(_this.height - _this.barHeight) && cap > 0) { _this.bar.style.top = (_this.height - _this.barHeight) + 'px'; _this.pY = e.pageY; _this.cacheTop = _this.height - _this.barHeight; return; } _this.bar.style.top = _this.cacheTop + cap + 'px'; _this.ele.scrollTop = parseInt(_this.bar.style.top)/(_this.height - _this.barHeight)*(_this.scrollHeight-_this.height); }; })(this), enter: (function(_this) { return function(e) { _this.bar.style.opacity = 1; }; })(this), leave: (function(_this) { return function(e) { _this.bar.style.opacity = 0; }; })(this) } } } function PrettyScroll(element, options) { new prettyScroll(element, options).initScrollBar(); } module.exports = PrettyScroll;