ScrollBar.js 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  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. this.thumbRef.current.removeEventListener('touchstart', this.onMouseDown, supportsPassive ? {
  102. passive: false
  103. } : false);
  104. this.thumbRef.current.removeEventListener('touchmove', this.onMouseMove, supportsPassive ? {
  105. passive: false
  106. } : false);
  107. this.thumbRef.current.removeEventListener('touchend', this.onMouseUp);
  108. raf.cancel(this.moveRaf);
  109. },
  110. // ======================= Thumb =======================
  111. onMouseDown: function onMouseDown(e) {
  112. var onStartMove = this.$props.onStartMove;
  113. _extends(this.state, {
  114. dragging: true,
  115. pageY: getPageY(e),
  116. startTop: this.getTop()
  117. });
  118. onStartMove();
  119. this.patchEvents();
  120. e.stopPropagation();
  121. e.preventDefault();
  122. },
  123. onMouseMove: function onMouseMove(e) {
  124. var _this$state = this.state,
  125. dragging = _this$state.dragging,
  126. pageY = _this$state.pageY,
  127. startTop = _this$state.startTop;
  128. var onScroll = this.$props.onScroll;
  129. raf.cancel(this.moveRaf);
  130. if (dragging) {
  131. var offsetY = getPageY(e) - pageY;
  132. var newTop = startTop + offsetY;
  133. var enableScrollRange = this.getEnableScrollRange();
  134. var enableHeightRange = this.getEnableHeightRange();
  135. var ptg = enableHeightRange ? newTop / enableHeightRange : 0;
  136. var newScrollTop = Math.ceil(ptg * enableScrollRange);
  137. this.moveRaf = raf(function () {
  138. onScroll(newScrollTop);
  139. });
  140. }
  141. },
  142. onMouseUp: function onMouseUp() {
  143. var onStopMove = this.$props.onStopMove;
  144. this.state.dragging = false;
  145. onStopMove();
  146. this.removeEvents();
  147. },
  148. // ===================== Calculate =====================
  149. getSpinHeight: function getSpinHeight() {
  150. var _this$$props = this.$props,
  151. height = _this$$props.height,
  152. count = _this$$props.count;
  153. var baseHeight = height / count * 10;
  154. baseHeight = Math.max(baseHeight, MIN_SIZE);
  155. baseHeight = Math.min(baseHeight, height / 2);
  156. return Math.floor(baseHeight);
  157. },
  158. getEnableScrollRange: function getEnableScrollRange() {
  159. var _this$$props2 = this.$props,
  160. scrollHeight = _this$$props2.scrollHeight,
  161. height = _this$$props2.height;
  162. return scrollHeight - height || 0;
  163. },
  164. getEnableHeightRange: function getEnableHeightRange() {
  165. var height = this.$props.height;
  166. var spinHeight = this.getSpinHeight();
  167. return height - spinHeight || 0;
  168. },
  169. getTop: function getTop() {
  170. var scrollTop = this.$props.scrollTop;
  171. var enableScrollRange = this.getEnableScrollRange();
  172. var enableHeightRange = this.getEnableHeightRange();
  173. if (scrollTop === 0 || enableScrollRange === 0) {
  174. return 0;
  175. }
  176. var ptg = scrollTop / enableScrollRange;
  177. return ptg * enableHeightRange;
  178. },
  179. // Not show scrollbar when height is large than scrollHeight
  180. showScroll: function showScroll() {
  181. var _this$$props3 = this.$props,
  182. height = _this$$props3.height,
  183. scrollHeight = _this$$props3.scrollHeight;
  184. return scrollHeight > height;
  185. }
  186. },
  187. render: function render() {
  188. // eslint-disable-next-line no-unused-vars
  189. var _this$state2 = this.state,
  190. dragging = _this$state2.dragging,
  191. visible = _this$state2.visible;
  192. var prefixCls = this.$props.prefixCls;
  193. var spinHeight = this.getSpinHeight() + 'px';
  194. var top = this.getTop() + 'px';
  195. var canScroll = this.showScroll();
  196. var mergedVisible = canScroll && visible;
  197. return _createVNode("div", {
  198. "ref": this.scrollbarRef,
  199. "class": classNames("".concat(prefixCls, "-scrollbar"), _defineProperty({}, "".concat(prefixCls, "-scrollbar-show"), canScroll)),
  200. "style": {
  201. width: '8px',
  202. top: 0,
  203. bottom: 0,
  204. right: 0,
  205. position: 'absolute',
  206. display: mergedVisible ? undefined : 'none'
  207. },
  208. "onMousedown": this.onContainerMouseDown,
  209. "onMousemove": this.delayHidden
  210. }, [_createVNode("div", {
  211. "ref": this.thumbRef,
  212. "class": classNames("".concat(prefixCls, "-scrollbar-thumb"), _defineProperty({}, "".concat(prefixCls, "-scrollbar-thumb-moving"), dragging)),
  213. "style": {
  214. width: '100%',
  215. height: spinHeight,
  216. top: top,
  217. left: 0,
  218. position: 'absolute',
  219. background: 'rgba(0, 0, 0, 0.5)',
  220. borderRadius: '99px',
  221. cursor: 'pointer',
  222. userSelect: 'none'
  223. },
  224. "onMousedown": this.onMouseDown
  225. }, null)]);
  226. }
  227. });