UNPKG

@tower1229/flow-ui

Version:

Highly customizable UI framework based Seajs/jQuery

305 lines (299 loc) 13.5 kB
/* * name:scrollbar * vertion: v2.2.8 * update: 部分情况无法检测元素尺寸bug * date: 2017-03-08 */ define('scroll-bar', function(require, exports, module) { "use strict"; seajs.importStyle('.scrollbar-ui .scroll_cont{position:relative}\ .scrollbar-ui .scroll_bar{position:absolute;z-index:8;cursor:default;-moz-user-select:none;opacity:0;background:#efefef;transition:opacity ease .3s}\ .scrollbar-ui-hover .scroll_bar{opacity:1}.scrollbar-ui .scroll_up,.scrollbar-ui .scroll_down{position:absolute;left:0;background:black}\ .scrollbar-ui .scroll_up{top:0}.scrollbar-ui .scroll_down{bottom:0}.scroll_up_on,.scroll_down_on{background:#ccc}\ .scrollbar-ui .scroll_slider{position:absolute;left:0;cursor:default;background:#666}.scroll_slider_on{background:#ccc}', module.uri); require('mousewheel'); var $ = window.$ || require('jquery'), base = require('base'), def = { wrap: null, //包裹元素,默认不指定,将新增div.scroll_cont monitor: false, //监听内容变化(用于多插件协作),布尔值,默认false overflow: "y", //滚动条方向,默认"y"(纵向),可选"x"(横向) keyway: 30, //键程,默认30(px) width: 8, //滚动条宽度,默认8(px) btnLength: 0, //按钮长度,默认0(不显示按钮) btnBreadth: '100%', //按钮宽度,默认与滚动条同宽 sliderWidth: '100%', //滑块宽度,默认与滚动条同宽 hideBar: false, //自动隐藏滚动条, ontop: function(){}, //滚动到顶部触发 onend: function(){} //滚动到底部触发 }; $.fn.scrollBar = function(config) { var opt = $.extend({}, def, config || {}); if (base.browser.isMobile) { return $(this).css({ 'overflow': 'auto', '-webkit-overflow-scrolling': 'touch' }).each(function(i,e){ if(opt.overflow=='y'){ $(e).on('scroll',function(){ var st = $(this).scrollTop(), sh = $(this).get(0).scrollHeight; if(st===0){ opt.ontop(); } if(st>=sh-$(this).height()){ opt.onend(); } }); }else if(opt.overflow=='x'){ $(e).on('scroll',function(){ var sl = $(this).scrollLeft(), sw = $(this).get(0).scrollWidth; if(sl===0){ opt.ontop(); } if(sl>=sw-$(this).width()){ opt.onend(); } }); } }); } return $(this).each(function(i, e) { var $this = $(e).addClass('scrollbar-ui').fadeIn(320), scrollCont, sliderBar, sliderLength, prop, wheelHandler, init, passive, setSlider, _length, _breadth, _posiLength, _posiBreadth, _scrollContLength, thisLength, sliderGone = 0, isWork = false, sliderBar = $("<div class='scroll_bar' onselectstart='return false;'>\ <div class='scroll_up'><!----></div>\ <div class='scroll_slider' unselectable='on'><!----></div>\ <div class='scroll_down'><!----></div>\ </div>"), btnUp = sliderBar.children('.scroll_up'), btnDown = sliderBar.children('.scroll_down'), scrollSlider = sliderBar.children('.scroll_slider'), statusLock = false, _thisInnerWidth = 0; //横向滚动内容宽度容器 if ($(e).data('scrollbar')) { return null; } //定义基本概念 switch (opt.overflow) { case 'x': _length = "width"; _breadth = "height"; _posiLength = "left"; _posiBreadth = "bottom"; break; default: _length = "height"; _breadth = "width"; _posiLength = "top"; _posiBreadth = "right"; break; } //获取scrollCont if ($this.find(opt.wrap).length) { scrollCont = $this.find(opt.wrap); } else { _thisInnerWidth = parseFloat($this.children().css(_length)); $this.wrapInner("<div class='scroll_cont'></div>"); scrollCont = $this.children('.scroll_cont'); } //插入滚动条 $this.append(sliderBar); if (opt.hideBar) { $this.on({ 'mouseenter': function() { $(this).addClass('scrollbar-ui-hover'); }, 'mouseleave': function() { $(this).removeClass('scrollbar-ui-hover'); } }); } else { $this.addClass('scrollbar-ui-hover'); } //预处理 thisLength = parseFloat($this.css(_length)); sliderBar. css(_length, "100%"). css(_breadth, opt.width). css(_posiBreadth, 0). css(_posiLength, 0); btnUp. css(_length, opt.btnLength). css(_breadth, opt.btnBreadth); btnDown. css(_length, opt.btnLength). css(_breadth, opt.btnBreadth); scrollSlider. css(_breadth, opt.sliderWidth). css(_posiBreadth, 0). css(_posiLength, 0); scrollSlider.bind('mousedown', function(e) { var pageLength, topCur, Move, docMouseMove = function(e2) { if (opt.overflow === 'y') { Move = e2.pageY - pageLength; } else { Move = e2.pageX - pageLength; } sliderGone = topCur + Move; setSlider(); return false; }, docMouseUp = function() { $(document) .unbind('mousemove', docMouseMove) .unbind('mouseup', docMouseUp); scrollSlider.removeClass('scroll_slider_on'); }; if (opt.overflow === 'y') { pageLength = e.pageY; } else { pageLength = e.pageX; } topCur = parseFloat($(this)._css(_posiLength)); $(this).addClass('scroll_slider_on'); $(document) .bind('mousemove', docMouseMove) .bind('mouseup', docMouseUp); }); btnUp.bind({ 'mousedown': function() { $(this).addClass('scroll_up_on'); }, 'mouseup': function() { sliderGone = sliderGone - opt.keyway / prop; setSlider(); $(this).removeClass('scroll_up_on'); } }); btnDown.bind({ 'mousedown': function() { $(this).addClass('scroll_down_on'); }, 'mouseup': function() { sliderGone = sliderGone + opt.keyway / prop; setSlider(); $(this).removeClass('scroll_down_on'); } }); //主方法 setSlider = function() { if (sliderGone <= opt.btnLength) { sliderGone = opt.btnLength; if(!statusLock){ statusLock = true; opt.ontop(); } } else if (sliderGone >= thisLength - opt.btnLength - sliderLength) { sliderGone = thisLength - opt.btnLength - sliderLength; if(!statusLock){ statusLock = true; opt.onend(); } } else{ statusLock = false; } scrollSlider._css(_posiLength, sliderGone); scrollCont._css(_posiLength, -((sliderGone - opt.btnLength) * prop)); }; init = function(fromMonitor) { //获取滚动内容长度 scrollCont.hide(); _scrollContLength = parseFloat(scrollCont.css(_length)); scrollCont.show(); if(_scrollContLength===0){ var scrollContClone = scrollCont.clone(); _scrollContLength = parseFloat(scrollContClone.css('visibility','hidden').appendTo('body').css(_length)); scrollContClone.remove(); if(_scrollContLength===0){ return console.warn('there is something wrong with "scrollBar()", check whether the element is hidden.'); } } if (_scrollContLength > thisLength) { //计算滚动条长度 sliderLength = parseFloat(scrollSlider.css(_length)) ? parseFloat(scrollSlider.css(_length)) : Math.round(thisLength / _scrollContLength * thisLength); sliderBar.show(); isWork = true; } else { sliderBar.hide(); isWork = false; } if (fromMonitor){ if(isWork){ //监听高度改变重新计算滑条长度 sliderLength = Math.round(thisLength / _scrollContLength * thisLength); }else{ //从无到有 return; } } scrollSlider.css(_length, sliderLength); //计算比率 prop = (_scrollContLength - thisLength) < 0 ? 0 : (_scrollContLength - thisLength) / (thisLength - opt.btnLength * 2 - sliderLength); setSlider(); if (fromMonitor && isWork) return;//监听高度改变不重复绑定事件 //滚轮事件 wheelHandler = function(e) { e.preventDefault(); e.stopPropagation(); if (_scrollContLength > thisLength) { var delta = e.deltaY * opt.keyway; sliderGone -= delta; setSlider(); } else { sliderGone = 0; setSlider(); if (!isWork) { $this.off('mousewheel'); } } }; $this.on('mousewheel', wheelHandler); }; //监听 passive = function(scrollCont) { var scTop, _sliderGone, _ssH = _scrollContLength, timer = setInterval(function(event) { //内容定位改变 _sliderGone = scrollCont._css(_posiLength); if (scTop != _sliderGone) { scrollSlider._css(_posiLength, opt.btnLength - _sliderGone / prop); scTop = _sliderGone; } //内容高度改变 if (parseFloat(scrollCont.css(_length)) != _ssH) { init(true); //区分来自监听的初始化 _ssH = parseFloat(scrollCont.css(_length)); } }, 160); $this.parent().on('DOMNodeRemoved',function(e){ if($(e.target).is($this)){ //DOM移除后释放全局变量 timer && clearInterval(timer); } }); }; //初始化 if (scrollCont.find('img').length) { require.async('img-loaded', function() { scrollCont.imagesLoaded(function() { init(false); if (opt.monitor) passive(scrollCont); }); }); } else { init(false); if (opt.monitor) passive(scrollCont); } $this.data('scrollbar', true); }); }; });