ScrollBar.js 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
  2. import _extends from "@babel/runtime/helpers/esm/extends";
  3. import { createVNode as _createVNode } from "vue";
  4. import { defineComponent, reactive } from 'vue';
  5. import classNames from '../_util/classNames';
  6. import createRef from '../_util/createRef';
  7. import raf from '../_util/raf';
  8. import supportsPassive from '../_util/supportsPassive';
  9. var MIN_SIZE = 20;
  10. function getPageY(e) {
  11. return 'touches' in e ? e.touches[0].pageY : e.pageY;
  12. }
  13. export default defineComponent({
  14. compatConfig: {
  15. MODE: 3
  16. },
  17. name: 'ScrollBar',
  18. inheritAttrs: false,
  19. props: {
  20. prefixCls: String,
  21. scrollTop: Number,
  22. scrollHeight: Number,
  23. height: Number,
  24. count: Number,
  25. onScroll: {
  26. type: Function
  27. },
  28. onStartMove: {
  29. type: Function
  30. },
  31. onStopMove: {
  32. type: Function
  33. }
  34. },
  35. setup: function setup() {
  36. return {
  37. moveRaf: null,
  38. scrollbarRef: createRef(),
  39. thumbRef: createRef(),
  40. visibleTimeout: null,
  41. state: reactive({
  42. dragging: false,
  43. pageY: null,
  44. startTop: null,
  45. visible: false
  46. })
  47. };
  48. },
  49. watch: {
  50. scrollTop: {
  51. handler: function handler() {
  52. this.delayHidden();
  53. },
  54. flush: 'post'
  55. }
  56. },
  57. mounted: function mounted() {
  58. var _this$scrollbarRef$cu, _this$thumbRef$curren;
  59. (_this$scrollbarRef$cu = this.scrollbarRef.current) === null || _this$scrollbarRef$cu === void 0 ? void 0 : _this$scrollbarRef$cu.addEventListener('touchstart', this.onScrollbarTouchStart, supportsPassive ? {
  60. passive: false
  61. } : false);
  62. (_this$thumbRef$curren = this.thumbRef.current) === null || _this$thumbRef$curren === void 0 ? void 0 : _this$thumbRef$curren.addEventListener('touchstart', this.onMouseDown, supportsPassive ? {
  63. passive: false
  64. } : false);
  65. },
  66. beforeUnmount: function beforeUnmount() {
  67. this.removeEvents();
  68. clearTimeout(this.visibleTimeout);
  69. },
  70. methods: {
  71. delayHidden: function delayHidden() {
  72. var _this = this;
  73. clearTimeout(this.visibleTimeout);
  74. this.state.visible = true;
  75. this.visibleTimeout = setTimeout(function () {
  76. _this.state.visible = false;
  77. }, 2000);
  78. },
  79. onScrollbarTouchStart: function onScrollbarTouchStart(e) {
  80. e.preventDefault();
  81. },
  82. onContainerMouseDown: function onContainerMouseDown(e) {
  83. e.stopPropagation();
  84. e.preventDefault();
  85. },
  86. // ======================= Clean =======================
  87. patchEvents: function patchEvents() {
  88. window.addEventListener('mousemove', this.onMouseMove);
  89. window.addEventListener('mouseup', this.onMouseUp);
  90. this.thumbRef.current.addEventListener('touchmove', this.onMouseMove, supportsPassive ? {
  91. passive: false
  92. } : false);
  93. this.thumbRef.current.addEventListener('touchend', this.onMouseUp);
  94. },
  95. removeEvents: function removeEvents() {
  96. window.removeEventListener('mousemove', this.onMouseMove);
  97. window.removeEventListener('mouseup', this.onMouseUp);
  98. this.scrollbarRef.current.removeEventListener('touchstart', this.onScrollbarTouchStart, supportsPassive ? {
  99. passive: false
  100. } : false);
  101. if (this.thumbRef.current) {
  102. this.thumbRef.current.removeEventListener('touchstart', this.onMouseDown, supportsPassive ? {
  103. passive: false
  104. } : false);
  105. this.thumbRef.current.removeEventListener('touchmove', this.onMouseMove, supportsPassive ? {
  106. passive: false
  107. } : false);
  108. this.thumbRef.current.removeEventListener('touchend', this.onMouseUp);
  109. }
  110. raf.cancel(this.moveRaf);
  111. },
  112. // ======================= Thumb =======================
  113. onMouseDown: function onMouseDown(e) {
  114. var onStartMove = this.$props.onStartMove;
  115. _extends(this.state, {
  116. dragging: true,
  117. pageY: getPageY(e),
  118. startTop: this.getTop()
  119. });
  120. onStartMove();
  121. this.patchEvents();
  122. e.stopPropagation();
  123. e.preventDefault();
  124. },
  125. onMouseMove: function onMouseMove(e) {
  126. var _this$state = this.state,
  127. dragging = _this$state.dragging,
  128. pageY = _this$state.pageY,
  129. startTop = _this$state.startTop;
  130. var onScroll = this.$props.onScroll;
  131. raf.cancel(this.moveRaf);
  132. if (dragging) {
  133. var offsetY = getPageY(e) - pageY;
  134. var newTop = startTop + offsetY;
  135. var enableScrollRange = this.getEnableScrollRange();
  136. var enableHeightRange = this.getEnableHeightRange();
  137. var ptg = enableHeightRange ? newTop / enableHeightRange : 0;
  138. var newScrollTop = Math.ceil(ptg * enableScrollRange);
  139. this.moveRaf = raf(function () {
  140. onScroll(newScrollTop);
  141. });
  142. }
  143. },
  144. onMouseUp: function onMouseUp() {
  145. var onStopMove = this.$props.onStopMove;
  146. this.state.dragging = false;
  147. onStopMove();
  148. this.removeEvents();
  149. },
  150. // ===================== Calculate =====================
  151. getSpinHeight: function getSpinHeight() {
  152. var _this$$props = this.$props,
  153. height = _this$$props.height,
  154. count = _this$$props.count;
  155. var baseHeight = height / count * 10;
  156. baseHeight = Math.max(baseHeight, MIN_SIZE);
  157. baseHeight = Math.min(baseHeight, height / 2);
  158. return Math.floor(baseHeight);
  159. },
  160. getEnableScrollRange: function getEnableScrollRange() {
  161. var _this$$props2 = this.$props,
  162. scrollHeight = _this$$props2.scrollHeight,
  163. height = _this$$props2.height;
  164. return scrollHeight - height || 0;
  165. },
  166. getEnableHeightRange: function getEnableHeightRange() {
  167. var height = this.$props.height;
  168. var spinHeight = this.getSpinHeight();
  169. return height - spinHeight || 0;
  170. },
  171. getTop: function getTop() {
  172. var scrollTop = this.$props.scrollTop;
  173. var enableScrollRange = this.getEnableScrollRange();
  174. var enableHeightRange = this.getEnableHeightRange();
  175. if (scrollTop === 0 || enableScrollRange === 0) {
  176. return 0;
  177. }
  178. var ptg = scrollTop / enableScrollRange;
  179. return ptg * enableHeightRange;
  180. },
  181. // Not show scrollbar when height is large than scrollHeight
  182. showScroll: function showScroll() {
  183. var _this$$props3 = this.$props,
  184. height = _this$$props3.height,
  185. scrollHeight = _this$$props3.scrollHeight;
  186. return scrollHeight > height;
  187. }
  188. },
  189. render: function render() {
  190. // eslint-disable-next-line no-unused-vars
  191. var _this$state2 = this.state,
  192. dragging = _this$state2.dragging,
  193. visible = _this$state2.visible;
  194. var prefixCls = this.$props.prefixCls;
  195. var spinHeight = this.getSpinHeight() + 'px';
  196. var top = this.getTop() + 'px';
  197. var canScroll = this.showScroll();
  198. var mergedVisible = canScroll && visible;
  199. return _createVNode("div", {
  200. "ref": this.scrollbarRef,
  201. "class": classNames("".concat(prefixCls, "-scrollbar"), _defineProperty({}, "".concat(prefixCls, "-scrollbar-show"), canScroll)),
  202. "style": {
  203. width: '8px',
  204. top: 0,
  205. bottom: 0,
  206. right: 0,
  207. position: 'absolute',
  208. display: mergedVisible ? undefined : 'none'
  209. },
  210. "onMousedown": this.onContainerMouseDown,
  211. "onMousemove": this.delayHidden
  212. }, [_createVNode("div", {
  213. "ref": this.thumbRef,
  214. "class": classNames("".concat(prefixCls, "-scrollbar-thumb"), _defineProperty({}, "".concat(prefixCls, "-scrollbar-thumb-moving"), dragging)),
  215. "style": {
  216. width: '100%',
  217. height: spinHeight,
  218. top: top,
  219. left: 0,
  220. position: 'absolute',
  221. background: 'rgba(0, 0, 0, 0.5)',
  222. borderRadius: '99px',
  223. cursor: 'pointer',
  224. userSelect: 'none'
  225. },
  226. "onMousedown": this.onMouseDown
  227. }, null)]);
  228. }
  229. });