diff --git a/assets/chrome.png b/assets/chrome.png new file mode 100644 index 0000000000000000000000000000000000000000..3979d9f9b451bb35ddb5cecb5564773090f240b4 Binary files /dev/null and b/assets/chrome.png differ diff --git a/assets/edge.png b/assets/edge.png new file mode 100644 index 0000000000000000000000000000000000000000..a99ee342474fbabb6b9b72a9c3be0908720aa494 Binary files /dev/null and b/assets/edge.png differ diff --git a/assets/firefox.png b/assets/firefox.png new file mode 100644 index 0000000000000000000000000000000000000000..a24fa33ec0c3348a3fd5baf4f1037e434fdd9ca0 Binary files /dev/null and b/assets/firefox.png differ diff --git a/assets/safari.png b/assets/safari.png new file mode 100644 index 0000000000000000000000000000000000000000..36043daa9a8c48b95b0c6ddbe99810f83d5b3116 Binary files /dev/null and b/assets/safari.png differ diff --git a/example.html b/example.html index 20c6719a646b5d9a87a9c078487e7751a4ef37b3..af2a33694aa5a391c3a5ec8c0abc31cd05186f4e 100644 --- a/example.html +++ b/example.html @@ -66,8 +66,8 @@ .table { border-collapse: collapse; - overflow: visible!important; - margin: 0!important; + overflow: visible !important; + margin: 0 !important; } .table td { @@ -77,7 +77,7 @@ text-align: center; color: #aaa; font-size: 14px; - padding: 0!important; + padding: 0 !important; } @@ -87,7 +87,7 @@
"+re(e.message+"",!0)+"";throw e}}return se.options=se.setOptions=function(e){return te(se.defaults,e),ie(se.defaults),se},se.getDefaults=_,se.defaults=t,se.use=function(a){var t,n=te({},a);a.renderer&&function(){var e,l=se.defaults.renderer||new H;for(e in a.renderer)!function(i){var s=l[i];l[i]=function(){for(var e=arguments.length,t=new Array(e),n=0;n
"+re(e.message+"",!0)+"";throw e}},se.Parser=ee,se.parser=ee.parse,se.Renderer=H,se.TextRenderer=J,se.Lexer=W,se.lexer=W.lex,se.Tokenizer=D,se.Slugger=K,se.parse=se}); \ No newline at end of file +!function(e,u){"object"==typeof exports&&"undefined"!=typeof module?module.exports=u():"function"==typeof define&&define.amd?define(u):(e="undefined"!=typeof globalThis?globalThis:e||self).marked=u()}(this,function(){"use strict";function r(e,u){for(var t=0;t
'+(t?e:H(e,!0))+"
\n":""+(t?e:H(e,!0))+"
\n"},u.blockquote=function(e){return"\n"+e+"\n"},u.html=function(e){return e},u.heading=function(e,u,t,n){return this.options.headerIds?"
"+e+"
\n"},u.table=function(e,u){return""+e+"
"},u.br=function(){return this.options.xhtml?""+se(e.message+"",!0)+"";throw e}}return ae.options=ae.setOptions=function(e){return re(ae.defaults,e),le(ae.defaults),ae},ae.getDefaults=y,ae.defaults=m,ae.use=function(l){var u,t=re({},l);l.renderer&&function(){var e,s=ae.defaults.renderer||new ne;for(e in l.renderer)!function(r){var i=s[r];s[r]=function(){for(var e=arguments.length,u=new Array(e),t=0;t
"+se(e.message+"",!0)+"";throw e}},ae.Parser=ue,ae.parser=ue.parse,ae.Renderer=ne,ae.TextRenderer=_,ae.Lexer=ee,ae.lexer=ee.lex,ae.Tokenizer=te,ae.Slugger=B,ae.parse=ae}); \ No newline at end of file diff --git a/package.json b/package.json index 4469fb390bd95c5939b48e6e49bceaa7edbcc01e..070a70ff36cec08c1ca58c28adc2bdb8f5c1629e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "x-scrollbar", - "version": "2.2.1", + "version": "2.3.0", "description": "这是一个自定义滚动条插件", "homepage": "https://gitee.com/null_720_0252/x-scrollbar", "main": "xscrollbar.js", diff --git a/xscrollbar.js b/xscrollbar.js index c9d7478af2805b0b131d88da7e11f3c5da2a4646..9d4b05d301fb91b494a6ab87992564ea33fe9668 100644 --- a/xscrollbar.js +++ b/xscrollbar.js @@ -1,404 +1,444 @@ /*! * x-scrollbar 自定义滚动条插件 - * 版本: v2.2.1 + * 版本: v2.3.0 * 作者: 清晨的阳光(QQ:765550360) * 许可: MIT * https://gitee.com/null_720_0252/x-scrollbar */ -class XScrollbar { - /** - * @param {*} dom DOM元素 - * @param {*} options 选项 - */ - constructor(dom, options) { - this.$container = dom; - if (this.$container.classList.contains('x-scrollbar-container')) return; - - // 移动端检测 - this.isMobile = window.navigator.userAgent.toLowerCase().includes('mobile'); - if (this.isMobile) return; - - // 合并配置 - let defaultOptions = { - // 禁用Y轴滚动(拨动鼠标滚轮时将作用于X轴) - disabledScrollY: false, - // 响应容器和内容大小改变(自动更新滚动条) - autoUpdate: true, - // 自动隐藏 - autoHide: true, - // 阻止向上传递滚动事件 - preventDefault: true, - // 平滑滚动 - smooth: true, - }; - Object.assign(this, defaultOptions, options); - - // 构造dom - this.$content = this.html2dom(''); - this.$railX = this.html2dom(''); - this.$railY = this.html2dom(''); - this.$thumbX = this.html2dom(''); - this.$thumbY = this.html2dom(''); - this.$railX.appendChild(this.$thumbX); - this.$railY.appendChild(this.$thumbY); - Array.from(this.$container.childNodes).forEach(node => this.$content.appendChild(node)); - this.$container.appendChild(this.$content); - this.$container.appendChild(this.$railX); - this.$container.appendChild(this.$railY); - // 自动隐藏 - this.$container.classList.add('x-scrollbar-container'); - if (!this.autoHide) this.$container.classList.add('x-scrollbar-keep'); - - // 绑定事件 - this.bindDrag(); - this.bindWheel(); - this.bindScroll(); - - // 自动更新 - if (this.autoUpdate) { - this.resizeObserver(); - } else { - this.update(); - } - } +if (typeof exports === 'object' && typeof module !== 'undefined') { + module.exports = XScrollbar; +} else { + window.XScrollbar = XScrollbar; +} - /** - * 设置滑块大小 - */ - setThumbSize() { - // (clientWidth / scrollWidth) = (滑块大小 / clientWidth) - // 最大滑动距离 = clientWidth - 滑块大小 - // 最大滚动距离 = scrollWidth - clientWidth - // (滑动距离 / 最大滑动距离) = (滚动距离 / 最大滚动距离) - - // 容器大小 - this.clientWidth = this.$container.clientWidth; - this.clientHeight = this.$container.clientHeight; - // 内容大小 - this.scrollWidth = this.$container.scrollWidth; - this.scrollHeight = this.$container.scrollHeight; - //是否存在滚动条 - this.hasXScrollbar = this.scrollWidth > this.clientWidth; - this.hasYScrollbar = this.scrollHeight > this.clientHeight; - //滑块大小 - this.thumbXWidth = Math.max((this.clientWidth / this.scrollWidth) * this.clientWidth, 30); - this.thumbYHeight = Math.max((this.clientHeight / this.scrollHeight) * this.clientHeight, 30); - //最大滑动距离 - this.thumbXMaxLeft = this.clientWidth - this.thumbXWidth; - this.thumbYMaxTop = this.clientHeight - this.thumbYHeight; - //最大滚动距离 - this.maxScrollLeft = this.scrollWidth - this.clientWidth; - this.maxScrollTop = this.scrollHeight - this.clientHeight; - - this.$railX.style.display = this.hasXScrollbar ? null : 'none'; - this.$railY.style.display = this.hasYScrollbar ? null : 'none'; - this.$thumbX.style.width = this.thumbXWidth + 'px'; - this.$thumbY.style.height = this.thumbYHeight + 'px'; +/** + * @param {*} dom DOM元素 + * @param {*} options 选项 + */ +function XScrollbar(dom, options) { + this.$container = dom; + if (this.$container.classList.contains('x-scrollbar-container')) return; + + // 移动端检测 + this.isMobile = window.navigator.userAgent.toLowerCase().indexOf('mobile') != -1; + if (this.isMobile) return; + + // 合并配置 + var defaultOptions = { + // 禁用Y轴滚动(拨动鼠标滚轮时将作用于X轴) + disabledScrollY: false, + // 响应容器和内容大小改变(自动更新滚动条) + autoUpdate: true, + // 自动隐藏 + autoHide: true, + // 阻止向上传递滚动事件 + preventDefault: true, + // 平滑滚动 + smooth: true + }; + this.assign(defaultOptions, options); + this.assign(this, defaultOptions); + + // 构造dom + this.$content = this.html2dom(''); + this.$railX = this.html2dom(''); + this.$railY = this.html2dom(''); + this.$thumbX = this.html2dom(''); + this.$thumbY = this.html2dom(''); + this.$railX.appendChild(this.$thumbX); + this.$railY.appendChild(this.$thumbY); + var childNodes = []; + Array.prototype.forEach.call(this.$container.childNodes, function(node) { childNodes.push(node) }); + childNodes.forEach((function (node) { this.$content.appendChild(node); }).bind(this)); + this.$container.appendChild(this.$content); + this.$container.appendChild(this.$railX); + this.$container.appendChild(this.$railY); + + // 自动隐藏 + this.$container.classList.add('x-scrollbar-container'); + if (!this.autoHide) this.$container.classList.add('x-scrollbar-keep'); + + // 绑定事件 + this.bindDrag(); + this.bindWheel(); + this.bindScroll(); + + // 自动更新 + if (this.autoUpdate) { + // 首次自动触发 + this.resizeObserver(); + } else { + this.update(); } +} - /** - * 拖动 - */ - bindDrag() { - // 是否被拖动选定 - let thumbXActive = false; - let thumbYActive = false; - // 上一次的拖动位置 - let screenX = null; - let screenY = null; - - this.$thumbX.addEventListener('mousedown', (e) => { - this.$railX.classList.add('x-scrollbar__rail-draging'); - thumbXActive = true; +/** + * 设置滑块大小 + */ +XScrollbar.prototype.setThumbSize = function () { + // (clientWidth / scrollWidth) = (滑块大小 / clientWidth) + // 最大滑动距离 = clientWidth - 滑块大小 + // 最大滚动距离 = scrollWidth - clientWidth + // (滑动距离 / 最大滑动距离) = (滚动距离 / 最大滚动距离) + + // 容器大小 + this.clientWidth = this.$container.clientWidth; + this.clientHeight = this.$container.clientHeight; + // 内容大小 + this.scrollWidth = this.$container.scrollWidth; + this.scrollHeight = this.$container.scrollHeight; + //是否存在滚动条 + this.hasXScrollbar = this.scrollWidth > this.clientWidth; + this.hasYScrollbar = this.scrollHeight > this.clientHeight; + //滑块大小 + this.thumbXWidth = Math.max((this.clientWidth / this.scrollWidth) * this.clientWidth, 30); + this.thumbYHeight = Math.max((this.clientHeight / this.scrollHeight) * this.clientHeight, 30); + //最大滑动距离 + this.thumbXMaxLeft = this.clientWidth - this.thumbXWidth; + this.thumbYMaxTop = this.clientHeight - this.thumbYHeight; + //最大滚动距离 + this.maxScrollLeft = this.scrollWidth - this.clientWidth; + this.maxScrollTop = this.scrollHeight - this.clientHeight; + + this.$railX.style.display = this.hasXScrollbar ? 'block' : 'none'; + this.$railY.style.display = this.hasYScrollbar ? 'block' : 'none'; + this.$thumbX.style.width = this.thumbXWidth + 'px'; + this.$thumbY.style.height = this.thumbYHeight + 'px'; +}; + +/** + * 拖动 + */ +XScrollbar.prototype.bindDrag = function () { + // 是否被拖动选定 + var thumbXActive = false; + var thumbYActive = false; + // 上一次的拖动位置 + var screenX = null; + var screenY = null; + + this.$thumbX.addEventListener('mousedown', (function (e) { + this.$railX.classList.add('x-scrollbar__rail-draging'); + thumbXActive = true; + screenX = e.screenX; + }).bind(this)); + + this.$thumbY.addEventListener('mousedown', (function (e) { + this.$railY.classList.add('x-scrollbar__rail-draging'); + thumbYActive = true; + screenY = e.screenY; + }).bind(this)); + + this.scrollDocumentMouseup = (function (e) { + this.$railX.classList.remove('x-scrollbar__rail-draging'); + this.$railY.classList.remove('x-scrollbar__rail-draging'); + thumbXActive = false; + thumbYActive = false; + }).bind(this); + document.addEventListener('mouseup', this.scrollDocumentMouseup); + + this.scrollDocumentMousemove = (function (e) { + if (!(thumbXActive || thumbYActive)) return; + e.preventDefault(); + + var axis = null; + var positionValue = null; + var scrollValue = null; + + if (thumbXActive) { + var offset = e.screenX - screenX; screenX = e.screenX; - }); - - this.$thumbY.addEventListener('mousedown', (e) => { - this.$railY.classList.add('x-scrollbar__rail-draging'); - thumbYActive = true; + axis = 'x'; + positionValue = Math.max(Math.min((this.left || 0) + offset, this.thumbXMaxLeft), 0); + scrollValue = Number(positionValue / this.thumbXMaxLeft * this.maxScrollLeft); + } else { + var offset = e.screenY - screenY; screenY = e.screenY; - }); - - this.scrollDocumentMouseup = (e) => { - this.$railX.classList.remove('x-scrollbar__rail-draging'); - this.$railY.classList.remove('x-scrollbar__rail-draging'); - thumbXActive = false; - thumbYActive = false; - }; - document.addEventListener('mouseup', this.scrollDocumentMouseup); - - this.scrollDocumentMousemove = (e) => { - if (!(thumbXActive || thumbYActive)) return; - e.preventDefault(); + axis = 'y'; + positionValue = Math.max(Math.min((this.top || 0) + offset, this.thumbYMaxTop), 0); + scrollValue = Number(positionValue / this.thumbYMaxTop * this.maxScrollTop); + } - let axis = null; - let positionValue = null; - let scrollValue = null; + this.scroll(axis, positionValue, scrollValue); + }).bind(this); + document.addEventListener('mousemove', this.scrollDocumentMousemove); +}; - if (thumbXActive) { - let offset = e.screenX - screenX; - screenX = e.screenX; - axis = 'x'; - positionValue = Math.max(Math.min((this.left || 0) + offset, this.thumbXMaxLeft), 0); - scrollValue = Number(positionValue / this.thumbXMaxLeft * this.maxScrollLeft); - } else { - let offset = e.screenY - screenY; - screenY = e.screenY; - axis = 'y'; - positionValue = Math.max(Math.min((this.top || 0) + offset, this.thumbYMaxTop), 0); - scrollValue = Number(positionValue / this.thumbYMaxTop * this.maxScrollTop); - } +/** + * 滚动 + */ +XScrollbar.prototype.bindWheel = function () { + var onWheel = (function (e, axis, delta) { + // 将滚动量转为像数值(https://developer.mozilla.org/zh-CN/docs/Web/API/Element/wheel_event) + if (e.deltaMode != 0) { + // 一行默认为40px + delta = delta * 40; + } - this.scroll(axis, positionValue, scrollValue); - }; - document.addEventListener('mousemove', this.scrollDocumentMousemove); - } + delta = parseInt(delta); - /** - * 滚动 - */ - bindWheel() { - let onWheel = (e, axis, delta) => { - // 将滚动量转为像数值(https://developer.mozilla.org/zh-CN/docs/Web/API/Element/wheel_event) - if (e.deltaMode != 0) { - // 一行默认为40px - delta = delta * 40; - } + var positionValue = null; + var scrollValue = null; - let positionValue = null; - let scrollValue = null; + if (axis == 'x') { + scrollValue = Math.max(Math.min((this.scrollLeft || 0) + delta, this.maxScrollLeft), 0); + positionValue = Number(scrollValue / this.maxScrollLeft * this.thumbXMaxLeft); + } else { + scrollValue = Math.max(Math.min((this.scrollTop || 0) + delta, this.maxScrollTop), 0); + positionValue = Number(scrollValue / this.maxScrollTop * this.thumbYMaxTop); + } - if (axis == 'x') { - scrollValue = Math.max(Math.min((this.scrollLeft || 0) + delta, this.maxScrollLeft), 0); - positionValue = Number(scrollValue / this.maxScrollLeft * this.thumbXMaxLeft); - } else { - scrollValue = Math.max(Math.min((this.scrollTop || 0) + delta, this.maxScrollTop), 0); - positionValue = Number(scrollValue / this.maxScrollTop * this.thumbYMaxTop); - } + // 阻止向上传递 || !(终点) + var toStart = scrollValue <= 0; + var toEnd = scrollValue >= (axis == 'x' ? this.maxScrollLeft : this.maxScrollTop); + if (this.preventDefault || !(toStart || toEnd)) { + e.preventDefault(); + e.stopPropagation(); + } - // 阻止向上传递 || !(终点) - let toStart = scrollValue <= 0; - let toEnd = scrollValue >= (axis == 'x' ? this.maxScrollLeft : this.maxScrollTop); - if (this.preventDefault || !(toStart || toEnd)) { - e.preventDefault(); - e.stopPropagation(); + if (this.mouseType == null) { + if (Math.abs(delta) < 50) { + // 初始滚动量小于90定义为触控板 + this.mouseType = 'touchpad'; + } else { + this.mouseType = 'wheel'; } + } - if (this.mouseType == null) { - if (Math.abs(delta) < 90) { - // 初始滚动量小于90定义为触控板 - this.mouseType = 'touchpad'; - } else { - this.mouseType = 'wheel'; - } - } + this.scroll(axis, positionValue, scrollValue, (this.smooth && this.mouseType == 'wheel')); + }).bind(this); - this.scroll(axis, positionValue, scrollValue, (this.smooth && this.mouseType == 'wheel')); - }; - this.onWheel = (e) => { - // e.deltaX 正值向下, 负值向上 - if (e.deltaX != 0 && this.hasXScrollbar) { - onWheel(e, 'x', e.deltaX); - } - if (e.deltaY != 0) { - // (shift键被按下 或 禁用Y轴滚动), 作用于x轴 - if ((e.deltaX == 0) && (e.shiftKey || this.disabledScrollY) && this.hasXScrollbar) { - onWheel(e, 'x', e.deltaY); - } else if (this.hasYScrollbar) { - onWheel(e, 'y', e.deltaY); - } + this.onWheel = (function (e) { + // e.deltaX 正值向下, 负值向上 + if (e.deltaX != 0 && this.hasXScrollbar) { + onWheel(e, 'x', e.deltaX); + } + if (e.deltaY != 0) { + // (shift键被按下 或 禁用Y轴滚动), 作用于x轴 + if ((e.deltaX == 0) && (e.shiftKey || this.disabledScrollY) && this.hasXScrollbar) { + onWheel(e, 'x', e.deltaY); + } else if (this.hasYScrollbar) { + onWheel(e, 'y', e.deltaY); } - }; - this.$container.addEventListener('wheel', this.onWheel, { passive: false }); + } + }).bind(this); + this.$container.addEventListener('wheel', this.onWheel); +}; + +/** + * 监听滚动事件 + * 用于响应从外部设置 scrollLeft/scrollTop 修正滚动条 + */ +XScrollbar.prototype.bindScroll = function () { + this.onScroll = (function (e) { + if (this.innerScroll) return; + this.update(); + }).bind(this); + this.$container.addEventListener('scroll', this.onScroll); +}; + +/** + * 滚动、修正滑块 + * @param {*} axis + * @param {*} positionValue + * @param {*} scrollValue + * @param {*} smooth = false + */ +XScrollbar.prototype.scroll = function (axis, positionValue, scrollValue, smooth) { + // 起始值 + var left = this.left; + var scrollLeft = this.scrollLeft; + var top = this.top; + var scrollTop = this.scrollTop; + + // 结束值 + if (axis == 'x') { + this.left = positionValue; + this.scrollLeft = scrollValue; + } else { + this.top = positionValue; + this.scrollTop = scrollValue; } - /** - * 监听滚动事件 - * 用于响应从外部设置 scrollLeft/scrollTop 修正滚动条 - */ - bindScroll() { - this.onScroll = (e) => { - if (this.innerScroll) return; - this.update(); - }; - this.$container.addEventListener('scroll', this.onScroll); + if (axis == 'x') { + if (this.xRefId) return; + } else { + if (this.yRefId) return; } - /** - * 滚动、修正滑块 - * @param {*} axis - * @param {*} positionValue - * @param {*} scrollValue - * @param {*} smooth - */ - scroll(axis, positionValue, scrollValue, smooth = false) { - // 起始值 - let left = this.left; - let scrollLeft = this.scrollLeft; - let top = this.top; - let scrollTop = this.scrollTop; - - // 结束值 - if (axis == 'x') { - this.left = positionValue; - this.scrollLeft = scrollValue; - } else { - this.top = positionValue; - this.scrollTop = scrollValue; + var end = (function () { + if (!(this.xRefId || this.yRefId)) { + requestAnimationFrame((function () { this.innerScroll = false }).bind(this)); } + }).bind(this); + + var animate = (function () { + // 从组件内部触发的滚动事件 + this.innerScroll = true; if (axis == 'x') { - if (this.xRefId) return; + left = this.easeout(left, this.left, smooth); + scrollLeft = this.easeout(scrollLeft, this.scrollLeft, smooth); + + // 滑块 + this.$thumbX.style.left = left + 'px'; + // 滚动 + this.$container.scrollLeft = scrollLeft; + // 轨道 + this.$railX.style.left = scrollLeft + 'px'; + this.$railY.style.right = (-scrollLeft) + 'px'; + + if (Math.abs(scrollLeft - this.scrollLeft) >= 1) { + this.xRefId = requestAnimationFrame(animate); + } else { + this.xRefId = null; + end(); + } } else { - if (this.yRefId) return; - } + top = this.easeout(top, this.top, smooth); + scrollTop = this.easeout(scrollTop, this.scrollTop, smooth); - let end = () => { - if (!(this.xRefId || this.yRefId)) { - requestAnimationFrame(() => this.innerScroll = false); - } - }; - - let animate = () => { - // 从组件内部触发的滚动事件 - this.innerScroll = true; - - if (axis == 'x') { - left = this.easeout(left, this.left, smooth); - scrollLeft = this.easeout(scrollLeft, this.scrollLeft, smooth); - - // 滑块 - this.$thumbX.style.left = `${left}px`; - // 滚动 - this.$container.scrollLeft = scrollLeft; - // 轨道 - this.$railX.style.left = `${scrollLeft}px`; - this.$railY.style.right = `${-(scrollLeft)}px`; - - if (Math.abs(scrollLeft - this.scrollLeft) >= 1) { - this.xRefId = requestAnimationFrame(animate); - } else { - this.xRefId = null; - end(); - } + this.$thumbY.style.top = top + 'px'; + this.$container.scrollTop = scrollTop; + this.$railX.style.bottom = (-scrollTop) + 'px'; + this.$railY.style.top = scrollTop + 'px'; + + if (Math.abs(scrollTop - this.scrollTop) >= 1) { + this.yRefId = requestAnimationFrame(animate); } else { - top = this.easeout(top, this.top, smooth); - scrollTop = this.easeout(scrollTop, this.scrollTop, smooth); - - this.$thumbY.style.top = `${top}px`; - this.$container.scrollTop = scrollTop; - this.$railX.style.bottom = `${-(scrollTop)}px`; - this.$railY.style.top = `${scrollTop}px`; - - if (Math.abs(scrollTop - this.scrollTop) >= 1) { - this.yRefId = requestAnimationFrame(animate); - } else { - this.yRefId = null; - end(); - } + this.yRefId = null; + end(); } - }; - requestAnimationFrame(animate); - } - - /** - * 缓动效果 - * @param {*} start - * @param {*} end - * @param {*} smooth - * @returns - */ - easeout(start, end, smooth) { - let v = null; - - if (!smooth || (Math.abs(end - start) <= 1)) { - v = end; - } else { - v = start + (end - start) / 4; } + }).bind(this); + requestAnimationFrame(animate); +}; + +/** + * 缓动效果 + * @param {*} start + * @param {*} end + * @param {*} smooth + * @returns + */ +XScrollbar.prototype.easeout = function (start, end, smooth) { + var v = null; - if ((end - start) > 0) { - return Math.ceil(v); - } else { - return Math.floor(v); - } + if (!smooth || (Math.abs(end - start) <= 1)) { + v = end; + } else { + v = start + (end - start) / 4; } - /** - * 使用滚动值修正滑块 - * 在 容器大小 或 内容大小 发生改变时调用 - */ - update() { - if (this.isMobile) return; + if ((end - start) > 0) { + return Math.ceil(v); + } else { + return Math.floor(v); + } +}; - // 先重置以更新滚动条的位置 - this.$railX.style.display = 'none'; - this.$railY.style.display = 'none'; - let scrollLeft = this.$container.scrollLeft; - let scrollTop = this.$container.scrollTop; +/** + * 使用滚动值修正滑块 + * 在 容器大小 或 内容大小 发生改变时调用 + */ +XScrollbar.prototype.update = function () { + if (this.isMobile) return; - this.setThumbSize(); + // 先重置以更新滚动条的位置 + this.$railX.style.display = 'none'; + this.$railY.style.display = 'none'; + var scrollLeft = this.$container.scrollLeft; + var scrollTop = this.$container.scrollTop; - let positionLeft = Number(scrollLeft / this.maxScrollLeft * this.thumbXMaxLeft) || 0; - this.scroll('x', positionLeft, scrollLeft); + this.setThumbSize(); - let positionTop = Number(scrollTop / this.maxScrollTop * this.thumbYMaxTop) || 0; - this.scroll('y', positionTop, scrollTop); - } + var positionLeft = Number(scrollLeft / this.maxScrollLeft * this.thumbXMaxLeft) || 0; + this.scroll('x', positionLeft, scrollLeft); + + var positionTop = Number(scrollTop / this.maxScrollTop * this.thumbYMaxTop) || 0; + this.scroll('y', positionTop, scrollTop); +}; - /** - * 响应容器和内容大小改变, 自动更新滚动条 - */ - resizeObserver() { - this.resizeObserver = new ResizeObserver(entries => { - let contentRect = entries[0].contentRect; +/** + * 响应容器和内容大小改变, 自动更新滚动条 + */ +XScrollbar.prototype.resizeObserver = function () { + if (typeof ResizeObserver != 'undefined') { + this.resizeObserver = new ResizeObserver((function (entries) { + var contentRect = entries[0].contentRect; if (!(contentRect.width || contentRect.height)) return; this.update(); - }); + }).bind(this)); this.resizeObserver.observe(this.$container); this.resizeObserver.observe(this.$content); + return; } - /** - * 销毁 - * @returns - */ - destroy() { - if (this.isMobile) return; - this.resizeObserver.disconnect(); - this.$container.classList.remove('x-scrollbar-container'); - this.$container.classList.remove('x-scrollbar-keep'); - Array.from(this.$content.childNodes).forEach(node => this.$container.appendChild(node)); - this.$container.removeChild(this.$content); - this.$container.removeChild(this.$railX); - this.$container.removeChild(this.$railY); - document.removeEventListener('mouseup', this.scrollDocumentMouseup); - document.removeEventListener('mousemove', this.scrollDocumentMousemove); - this.$container.removeEventListener('wheel', this.wheel); - this.$container.removeEventListener('scroll', this.onScroll); - } - - /** - * html 转 dom - * @param {*} html - * @returns - */ - html2dom(html) { - let element = document.createElement('div'); - element.innerHTML = html; - let children = Array.from(element.children); - if (children.length <= 1) { - return children[0]; - } else { - return children; + var containerRect = this.$container.getBoundingClientRect(); + var contentRect = this.$content.getBoundingClientRect(); + var resizeObserver = (function () { + var _containerRect = this.$container.getBoundingClientRect(); + var _contentRect = this.$content.getBoundingClientRect(); + if ((containerRect.width != _containerRect.width) || (containerRect.height != _containerRect.height) || (contentRect.width != _contentRect.width) || (contentRect.height != _contentRect.height)) { + this.update(); } + containerRect = _containerRect; + contentRect = _contentRect; + requestAnimationFrame(resizeObserver); + }).bind(this); + requestAnimationFrame(resizeObserver); + this.update(); +}; + +/** + * 销毁 + */ +XScrollbar.prototype.destroy = function () { + if (this.isMobile) return; + this.resizeObserver.disconnect(); + this.$container.classList.remove('x-scrollbar-container'); + this.$container.classList.remove('x-scrollbar-keep'); + var childNodes = []; + Array.prototype.forEach.call(this.$container.content, function(node) { childNodes.push(node) }); + childNodes.forEach((function (node) { this.$container.appendChild(node) }).bind(this)); + this.$container.removeChild(this.$content); + this.$container.removeChild(this.$railX); + this.$container.removeChild(this.$railY); + document.removeEventListener('mouseup', this.scrollDocumentMouseup); + document.removeEventListener('mousemove', this.scrollDocumentMousemove); + this.$container.removeEventListener('wheel', this.wheel); + this.$container.removeEventListener('scroll', this.onScroll); +}; + +/** + * html 转 dom + * @param {*} html + * @returns + */ +XScrollbar.prototype.html2dom = function (html) { + var element = document.createElement('div'); + element.innerHTML = html; + var children = element.children; + if (children.length <= 1) { + return children[0]; + } else { + return children; } -} +}; -if (typeof exports === 'object' && typeof module !== 'undefined') { - module.exports = XScrollbar; -} else { - window.XScrollbar = XScrollbar; -} \ No newline at end of file +/** + * 合并配置 + * @param {*} target + * @param {*} source + * @returns + */ +XScrollbar.prototype.assign = function (target, source) { + target = target || {}; + source = source || {}; + for (key in source) { + target[key] = source[key]; + } + return target; +}; \ No newline at end of file