ScrollBar.js 7.3 KB

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