ea95c04b88c4638794036898061e29d1dd8bd652573353d603ccb9af0b06de43b01fd90dd31e339f1e5f7a7508b5df3595b984e7b64bdd78c9d510b19eccf6 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', { value: true });
  3. var vue = require('vue');
  4. var defaults = require('../defaults.js');
  5. var props = require('../props.js');
  6. var utils = require('../utils.js');
  7. var util = require('../../../scrollbar/src/util.js');
  8. var index = require('../../../../hooks/use-namespace/index.js');
  9. var raf = require('../../../../utils/raf.js');
  10. const ScrollBar = vue.defineComponent({
  11. name: "ElVirtualScrollBar",
  12. props: props.virtualizedScrollbarProps,
  13. emits: ["scroll", "start-move", "stop-move"],
  14. setup(props, { emit }) {
  15. const GAP = vue.computed(() => props.startGap + props.endGap);
  16. const nsVirtualScrollbar = index.useNamespace("virtual-scrollbar");
  17. const nsScrollbar = index.useNamespace("scrollbar");
  18. const trackRef = vue.ref();
  19. const thumbRef = vue.ref();
  20. let frameHandle = null;
  21. let onselectstartStore = null;
  22. const state = vue.reactive({
  23. isDragging: false,
  24. traveled: 0
  25. });
  26. const bar = vue.computed(() => util.BAR_MAP[props.layout]);
  27. const trackSize = vue.computed(() => props.clientSize - vue.unref(GAP));
  28. const trackStyle = vue.computed(() => ({
  29. position: "absolute",
  30. width: `${defaults.HORIZONTAL === props.layout ? trackSize.value : props.scrollbarSize}px`,
  31. height: `${defaults.HORIZONTAL === props.layout ? props.scrollbarSize : trackSize.value}px`,
  32. [defaults.ScrollbarDirKey[props.layout]]: "2px",
  33. right: "2px",
  34. bottom: "2px",
  35. borderRadius: "4px"
  36. }));
  37. const thumbSize = vue.computed(() => {
  38. const ratio = props.ratio;
  39. if (ratio >= 100) {
  40. return Number.POSITIVE_INFINITY;
  41. }
  42. if (ratio >= 50) {
  43. return ratio * trackSize.value / 100;
  44. }
  45. const SCROLLBAR_MAX_SIZE = trackSize.value / 3;
  46. return Math.floor(Math.min(Math.max(ratio * trackSize.value / 100, defaults.SCROLLBAR_MIN_SIZE), SCROLLBAR_MAX_SIZE));
  47. });
  48. const thumbStyle = vue.computed(() => {
  49. if (!Number.isFinite(thumbSize.value)) {
  50. return {
  51. display: "none"
  52. };
  53. }
  54. const thumb = `${thumbSize.value}px`;
  55. const style = utils.renderThumbStyle({
  56. bar: bar.value,
  57. size: thumb,
  58. move: state.traveled
  59. }, props.layout);
  60. return style;
  61. });
  62. const totalSteps = vue.computed(() => Math.ceil(props.clientSize - thumbSize.value - vue.unref(GAP)));
  63. const attachEvents = () => {
  64. window.addEventListener("mousemove", onMouseMove);
  65. window.addEventListener("mouseup", onMouseUp);
  66. const thumbEl = vue.unref(thumbRef);
  67. if (!thumbEl)
  68. return;
  69. onselectstartStore = document.onselectstart;
  70. document.onselectstart = () => false;
  71. thumbEl.addEventListener("touchmove", onMouseMove, { passive: true });
  72. thumbEl.addEventListener("touchend", onMouseUp);
  73. };
  74. const detachEvents = () => {
  75. window.removeEventListener("mousemove", onMouseMove);
  76. window.removeEventListener("mouseup", onMouseUp);
  77. document.onselectstart = onselectstartStore;
  78. onselectstartStore = null;
  79. const thumbEl = vue.unref(thumbRef);
  80. if (!thumbEl)
  81. return;
  82. thumbEl.removeEventListener("touchmove", onMouseMove);
  83. thumbEl.removeEventListener("touchend", onMouseUp);
  84. };
  85. const onThumbMouseDown = (e) => {
  86. e.stopImmediatePropagation();
  87. if (e.ctrlKey || [1, 2].includes(e.button)) {
  88. return;
  89. }
  90. state.isDragging = true;
  91. state[bar.value.axis] = e.currentTarget[bar.value.offset] - (e[bar.value.client] - e.currentTarget.getBoundingClientRect()[bar.value.direction]);
  92. emit("start-move");
  93. attachEvents();
  94. };
  95. const onMouseUp = () => {
  96. state.isDragging = false;
  97. state[bar.value.axis] = 0;
  98. emit("stop-move");
  99. detachEvents();
  100. };
  101. const onMouseMove = (e) => {
  102. const { isDragging } = state;
  103. if (!isDragging)
  104. return;
  105. if (!thumbRef.value || !trackRef.value)
  106. return;
  107. const prevPage = state[bar.value.axis];
  108. if (!prevPage)
  109. return;
  110. raf.cAF(frameHandle);
  111. const offset = (trackRef.value.getBoundingClientRect()[bar.value.direction] - e[bar.value.client]) * -1;
  112. const thumbClickPosition = thumbRef.value[bar.value.offset] - prevPage;
  113. const distance = offset - thumbClickPosition;
  114. frameHandle = raf.rAF(() => {
  115. state.traveled = Math.max(0, Math.min(distance, totalSteps.value));
  116. emit("scroll", distance, totalSteps.value);
  117. });
  118. };
  119. const clickTrackHandler = (e) => {
  120. const offset = Math.abs(e.target.getBoundingClientRect()[bar.value.direction] - e[bar.value.client]);
  121. const thumbHalf = thumbRef.value[bar.value.offset] / 2;
  122. const distance = offset - thumbHalf;
  123. state.traveled = Math.max(0, Math.min(distance, totalSteps.value));
  124. emit("scroll", distance, totalSteps.value);
  125. };
  126. vue.watch(() => props.scrollFrom, (v) => {
  127. if (state.isDragging)
  128. return;
  129. state.traveled = Math.ceil(v * totalSteps.value);
  130. });
  131. vue.onBeforeUnmount(() => {
  132. detachEvents();
  133. });
  134. return () => {
  135. return vue.h("div", {
  136. role: "presentation",
  137. ref: trackRef,
  138. class: [
  139. nsVirtualScrollbar.b(),
  140. props.class,
  141. (props.alwaysOn || state.isDragging) && "always-on"
  142. ],
  143. style: trackStyle.value,
  144. onMousedown: vue.withModifiers(clickTrackHandler, ["stop", "prevent"]),
  145. onTouchstartPrevent: onThumbMouseDown
  146. }, vue.h("div", {
  147. ref: thumbRef,
  148. class: nsScrollbar.e("thumb"),
  149. style: thumbStyle.value,
  150. onMousedown: onThumbMouseDown
  151. }, []));
  152. };
  153. }
  154. });
  155. exports["default"] = ScrollBar;
  156. //# sourceMappingURL=scrollbar.js.map