scrollbar.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. define(function(require, exports, module) {
  2. "use strict";
  3. var Util = require('../util');
  4. var Animate = require('../animate');
  5. var MAX_BOUNCE_DISTANCE = 40;
  6. var MIN_BAR_SCROLLED_SIZE = 10;
  7. var MIN_BAR_SIZE = 50;
  8. var transform = Util.prefixStyle("transform");
  9. var transformStr = Util.vendor ? ["-", Util.vendor, "-transform"].join("") : "transform";
  10. var transition = Util.prefixStyle("transition");
  11. var borderRadius = Util.prefixStyle("borderRadius");
  12. var transitionDuration = Util.prefixStyle("transitionDuration");
  13. var ScrollBar = function(cfg) {
  14. this.userConfig = Util.mix({
  15. MIN_BAR_SCROLLED_SIZE:MIN_BAR_SCROLLED_SIZE,
  16. MIN_BAR_SIZE:MIN_BAR_SIZE,
  17. MAX_BOUNCE_DISTANCE:MAX_BOUNCE_DISTANCE,
  18. spacing:5
  19. }, cfg);
  20. this.init(cfg.xscroll);
  21. }
  22. Util.mix(ScrollBar.prototype, {
  23. init: function(xscroll) {
  24. var self = this;
  25. self.xscroll = xscroll;
  26. self.type = self.userConfig.type;
  27. self.isY = self.type == "y" ? true : false;
  28. self.scrollTopOrLeft = self.isY ? "scrollTop" : "scrollLeft";
  29. },
  30. destroy: function() {
  31. var self = this;
  32. Util.remove(self.scrollbar);
  33. self.xscroll.off("scroll", self._scrollHandler, self);
  34. self.xscroll.off("scrollend", self._scrollEndHandler, self);
  35. },
  36. render: function() {
  37. var self = this;
  38. var xscroll = self.xscroll;
  39. var boundry = xscroll.boundry;
  40. var indicatorInsets = self.xscroll.userConfig.indicatorInsets;
  41. var translateZ = xscroll.userConfig.gpuAcceleration ? " translateZ(0) " : "";
  42. var transform = translateZ ? transformStr + ":" + translateZ + ";" : "";
  43. var commonCss = "opacity:0;position:absolute;z-index:999;overflow:hidden;-webkit-border-radius:3px;-moz-border-radius:3px;-o-border-radius:3px;" + transform;
  44. indicatorInsets._xright = indicatorInsets.right + indicatorInsets.spacing;
  45. indicatorInsets._xbottom = indicatorInsets.bottom + indicatorInsets.spacing;
  46. var css = self.isY ?
  47. Util.substitute("width:{width}px;bottom:{_xbottom}px;top:{top}px;right:{right}px;", indicatorInsets) + commonCss :
  48. Util.substitute("height:{width}px;left:{left}px;right:{_xright}px;bottom:{bottom}px;",indicatorInsets) + commonCss;
  49. if(!self.scrollbar){
  50. self.scrollbar = document.createElement("div");
  51. self.indicate = document.createElement("div");
  52. xscroll.renderTo.appendChild(self.scrollbar);
  53. self.scrollbar.appendChild(self.indicate);
  54. }
  55. self.scrollbar.style.cssText = css;
  56. var size = self.isY ? "width:100%;" : "height:100%;";
  57. self.indicate.style.cssText = size + "position:absolute;background:rgba(0,0,0,0.3);-webkit-border-radius:3px;-moz-border-radius:3px;-o-border-radius:3px;"
  58. self._update();
  59. self.hide(0);
  60. self._bindEvt();
  61. },
  62. _update: function(pos, duration, easing, callback) {
  63. var self = this;
  64. var pos = undefined === pos ? (self.isY ? self.xscroll.getScrollTop() : self.xscroll.getScrollLeft()) : pos;
  65. var barInfo = self.computeScrollBar(pos);
  66. var size = self.isY ? "height" : "width";
  67. self.indicate.style[size] = Math.round(barInfo.size) + "px";
  68. if (duration && easing) {
  69. self.scrollTo(barInfo.pos, duration, easing, callback);
  70. } else {
  71. self.moveTo(barInfo.pos);
  72. }
  73. },
  74. //compute the position and size of the scrollbar
  75. computeScrollBar: function(pos) {
  76. var self = this;
  77. var type = self.isY ? "y" : "x";
  78. var spacing = self.userConfig.spacing;
  79. var xscroll = self.xscroll;
  80. var boundry = xscroll.boundry;
  81. var userConfig = self.userConfig;
  82. var pos = self.isY ? Math.round(pos) + boundry._xtop : Math.round(pos) + boundry._xleft;
  83. var MIN_BAR_SCROLLED_SIZE = userConfig.MIN_BAR_SCROLLED_SIZE;
  84. var MIN_BAR_SIZE = userConfig.MIN_BAR_SIZE;
  85. var MAX_BOUNCE_DISTANCE = userConfig.MAX_BOUNCE_DISTANCE;
  86. self.containerSize = self.isY ? xscroll.containerHeight + boundry._xtop + boundry._xbottom : self.xscroll.containerWidth + boundry._xright + boundry._xleft;
  87. self.size = self.isY ? boundry.cfg.height : boundry.cfg.width;
  88. self.indicateSize = self.isY ? boundry.cfg.height - spacing * 2 : boundry.cfg.width - spacing * 2;
  89. var indicateSize = self.indicateSize;
  90. var containerSize = self.containerSize;
  91. var barPos = indicateSize * pos / containerSize;
  92. var barSize = Math.round(indicateSize * self.size / containerSize);
  93. var overTop = self.isY ? xscroll.getBoundryOutTop() : xscroll.getBoundryOutLeft();
  94. var overBottom = self.isY ? xscroll.getBoundryOutBottom() : xscroll.getBoundryOutRight();
  95. var barShiftSize = MIN_BAR_SIZE - barSize > 0 ? MIN_BAR_SIZE - barSize : 0;
  96. barSize = barSize < MIN_BAR_SIZE ? MIN_BAR_SIZE : barSize;
  97. barPos = (indicateSize - barShiftSize) * pos / containerSize;
  98. if (overTop >= 0) {
  99. var pct = overTop / MAX_BOUNCE_DISTANCE;
  100. pct = pct > 1 ? 1 : pct;
  101. barPos = - pct * (barSize - MIN_BAR_SCROLLED_SIZE)
  102. }
  103. if (overBottom >= 0) {
  104. var pct = overBottom / MAX_BOUNCE_DISTANCE;
  105. pct = pct > 1 ? 1 : pct;
  106. barPos = pct * (barSize - MIN_BAR_SCROLLED_SIZE) + indicateSize - barSize;
  107. }
  108. self.barPos = Math.round(barPos);
  109. return {
  110. size: Math.round(barSize),
  111. pos: self.barPos
  112. };
  113. },
  114. scrollTo: function(pos, duration, easing, callback) {
  115. var self = this;
  116. self.show();
  117. var translateZ = self.xscroll.userConfig.gpuAcceleration ? " translateZ(0) " : "";
  118. var config = {
  119. css: {
  120. transform: self.isY ? "translateY(" + pos + "px)" + translateZ : "translateX(" + pos + "px)" + translateZ
  121. },
  122. duration: duration,
  123. easing: easing,
  124. useTransition: self.xscroll.userConfig.useTransition,
  125. end: callback
  126. };
  127. self.__timer = self.__timer || new Animate(self.indicate, config);
  128. //run
  129. self.__timer.stop();
  130. self.__timer.reset(config);
  131. self.__timer.run();
  132. },
  133. moveTo: function(pos) {
  134. var self = this;
  135. self.show();
  136. var translateZ = self.xscroll.userConfig.gpuAcceleration ? " translateZ(0) " : "";
  137. self.isY ? self.indicate.style[transform] = "translateY(" + pos + "px) " + translateZ : self.indicate.style[transform] = "translateX(" + pos + "px) " + translateZ
  138. self.indicate.style[transition] = "";
  139. },
  140. _scrollHandler: function(e) {
  141. var self = this;
  142. self._update(e[self.scrollTopOrLeft]);
  143. return self;
  144. },
  145. isBoundryOut: function() {
  146. var self = this;
  147. return !self.isY ? (self.xscroll.isBoundryOutLeft() || self.xscroll.isBoundryOutRight()) : (self.xscroll.isBoundryOutTop() || self.xscroll.isBoundryOutBottom());
  148. },
  149. _scrollEndHandler: function(e) {
  150. var self = this;
  151. if (!self.isBoundryOut()) {
  152. self._update(e[self.scrollTopOrLeft]);
  153. self.hide();
  154. }
  155. return self;
  156. },
  157. _bindEvt: function() {
  158. var self = this;
  159. if (self.__isEvtBind) return;
  160. self.__isEvtBind = true;
  161. self.xscroll.on("scroll", self._scrollHandler, self);
  162. self.xscroll.on("scrollend", self._scrollEndHandler, self);
  163. },
  164. reset: function() {
  165. var self = this;
  166. self.pos = 0;
  167. self._update();
  168. },
  169. hide: function(duration, easing, delay) {
  170. var self = this;
  171. var duration = duration >= 0 ? duration : 300;
  172. var easing = easing || "ease-out";
  173. var delay = delay >= 0 ? delay : 100;
  174. self.scrollbar.style.opacity = 0;
  175. self.scrollbar.style[transition] = ["opacity ", duration, "ms ", " ease-out ", delay, "ms"].join("");
  176. },
  177. show: function() {
  178. var self = this;
  179. self.scrollbar.style.opacity = 1;
  180. self.scrollbar.style[transition] = "";
  181. }
  182. });
  183. if (typeof module == 'object' && module.exports) {
  184. module.exports = ScrollBar;
  185. }
  186. /** ignored by jsdoc **/
  187. else {
  188. return ScrollBar;
  189. }
  190. });