scrollbar.mjs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. import { g as getDocument } from '../shared/ssr-window.esm.mjs';
  2. import { m as makeElementsArray, i as classesToTokens, c as createElement, n as nextTick, b as elementOffset } from '../shared/utils.mjs';
  3. import { c as createElementIfNotDefined } from '../shared/create-element-if-not-defined.mjs';
  4. import { c as classesToSelector } from '../shared/classes-to-selector.mjs';
  5. function Scrollbar(_ref) {
  6. let {
  7. swiper,
  8. extendParams,
  9. on,
  10. emit
  11. } = _ref;
  12. const document = getDocument();
  13. let isTouched = false;
  14. let timeout = null;
  15. let dragTimeout = null;
  16. let dragStartPos;
  17. let dragSize;
  18. let trackSize;
  19. let divider;
  20. extendParams({
  21. scrollbar: {
  22. el: null,
  23. dragSize: 'auto',
  24. hide: false,
  25. draggable: false,
  26. snapOnRelease: true,
  27. lockClass: 'swiper-scrollbar-lock',
  28. dragClass: 'swiper-scrollbar-drag',
  29. scrollbarDisabledClass: 'swiper-scrollbar-disabled',
  30. horizontalClass: `swiper-scrollbar-horizontal`,
  31. verticalClass: `swiper-scrollbar-vertical`
  32. }
  33. });
  34. swiper.scrollbar = {
  35. el: null,
  36. dragEl: null
  37. };
  38. function setTranslate() {
  39. if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) return;
  40. const {
  41. scrollbar,
  42. rtlTranslate: rtl
  43. } = swiper;
  44. const {
  45. dragEl,
  46. el
  47. } = scrollbar;
  48. const params = swiper.params.scrollbar;
  49. const progress = swiper.params.loop ? swiper.progressLoop : swiper.progress;
  50. let newSize = dragSize;
  51. let newPos = (trackSize - dragSize) * progress;
  52. if (rtl) {
  53. newPos = -newPos;
  54. if (newPos > 0) {
  55. newSize = dragSize - newPos;
  56. newPos = 0;
  57. } else if (-newPos + dragSize > trackSize) {
  58. newSize = trackSize + newPos;
  59. }
  60. } else if (newPos < 0) {
  61. newSize = dragSize + newPos;
  62. newPos = 0;
  63. } else if (newPos + dragSize > trackSize) {
  64. newSize = trackSize - newPos;
  65. }
  66. if (swiper.isHorizontal()) {
  67. dragEl.style.transform = `translate3d(${newPos}px, 0, 0)`;
  68. dragEl.style.width = `${newSize}px`;
  69. } else {
  70. dragEl.style.transform = `translate3d(0px, ${newPos}px, 0)`;
  71. dragEl.style.height = `${newSize}px`;
  72. }
  73. if (params.hide) {
  74. clearTimeout(timeout);
  75. el.style.opacity = 1;
  76. timeout = setTimeout(() => {
  77. el.style.opacity = 0;
  78. el.style.transitionDuration = '400ms';
  79. }, 1000);
  80. }
  81. }
  82. function setTransition(duration) {
  83. if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) return;
  84. swiper.scrollbar.dragEl.style.transitionDuration = `${duration}ms`;
  85. }
  86. function updateSize() {
  87. if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) return;
  88. const {
  89. scrollbar
  90. } = swiper;
  91. const {
  92. dragEl,
  93. el
  94. } = scrollbar;
  95. dragEl.style.width = '';
  96. dragEl.style.height = '';
  97. trackSize = swiper.isHorizontal() ? el.offsetWidth : el.offsetHeight;
  98. divider = swiper.size / (swiper.virtualSize + swiper.params.slidesOffsetBefore - (swiper.params.centeredSlides ? swiper.snapGrid[0] : 0));
  99. if (swiper.params.scrollbar.dragSize === 'auto') {
  100. dragSize = trackSize * divider;
  101. } else {
  102. dragSize = parseInt(swiper.params.scrollbar.dragSize, 10);
  103. }
  104. if (swiper.isHorizontal()) {
  105. dragEl.style.width = `${dragSize}px`;
  106. } else {
  107. dragEl.style.height = `${dragSize}px`;
  108. }
  109. if (divider >= 1) {
  110. el.style.display = 'none';
  111. } else {
  112. el.style.display = '';
  113. }
  114. if (swiper.params.scrollbar.hide) {
  115. el.style.opacity = 0;
  116. }
  117. if (swiper.params.watchOverflow && swiper.enabled) {
  118. scrollbar.el.classList[swiper.isLocked ? 'add' : 'remove'](swiper.params.scrollbar.lockClass);
  119. }
  120. }
  121. function getPointerPosition(e) {
  122. return swiper.isHorizontal() ? e.clientX : e.clientY;
  123. }
  124. function setDragPosition(e) {
  125. const {
  126. scrollbar,
  127. rtlTranslate: rtl
  128. } = swiper;
  129. const {
  130. el
  131. } = scrollbar;
  132. let positionRatio;
  133. positionRatio = (getPointerPosition(e) - elementOffset(el)[swiper.isHorizontal() ? 'left' : 'top'] - (dragStartPos !== null ? dragStartPos : dragSize / 2)) / (trackSize - dragSize);
  134. positionRatio = Math.max(Math.min(positionRatio, 1), 0);
  135. if (rtl) {
  136. positionRatio = 1 - positionRatio;
  137. }
  138. const position = swiper.minTranslate() + (swiper.maxTranslate() - swiper.minTranslate()) * positionRatio;
  139. swiper.updateProgress(position);
  140. swiper.setTranslate(position);
  141. swiper.updateActiveIndex();
  142. swiper.updateSlidesClasses();
  143. }
  144. function onDragStart(e) {
  145. const params = swiper.params.scrollbar;
  146. const {
  147. scrollbar,
  148. wrapperEl
  149. } = swiper;
  150. const {
  151. el,
  152. dragEl
  153. } = scrollbar;
  154. isTouched = true;
  155. dragStartPos = e.target === dragEl ? getPointerPosition(e) - e.target.getBoundingClientRect()[swiper.isHorizontal() ? 'left' : 'top'] : null;
  156. e.preventDefault();
  157. e.stopPropagation();
  158. wrapperEl.style.transitionDuration = '100ms';
  159. dragEl.style.transitionDuration = '100ms';
  160. setDragPosition(e);
  161. clearTimeout(dragTimeout);
  162. el.style.transitionDuration = '0ms';
  163. if (params.hide) {
  164. el.style.opacity = 1;
  165. }
  166. if (swiper.params.cssMode) {
  167. swiper.wrapperEl.style['scroll-snap-type'] = 'none';
  168. }
  169. emit('scrollbarDragStart', e);
  170. }
  171. function onDragMove(e) {
  172. const {
  173. scrollbar,
  174. wrapperEl
  175. } = swiper;
  176. const {
  177. el,
  178. dragEl
  179. } = scrollbar;
  180. if (!isTouched) return;
  181. if (e.preventDefault && e.cancelable) e.preventDefault();else e.returnValue = false;
  182. setDragPosition(e);
  183. wrapperEl.style.transitionDuration = '0ms';
  184. el.style.transitionDuration = '0ms';
  185. dragEl.style.transitionDuration = '0ms';
  186. emit('scrollbarDragMove', e);
  187. }
  188. function onDragEnd(e) {
  189. const params = swiper.params.scrollbar;
  190. const {
  191. scrollbar,
  192. wrapperEl
  193. } = swiper;
  194. const {
  195. el
  196. } = scrollbar;
  197. if (!isTouched) return;
  198. isTouched = false;
  199. if (swiper.params.cssMode) {
  200. swiper.wrapperEl.style['scroll-snap-type'] = '';
  201. wrapperEl.style.transitionDuration = '';
  202. }
  203. if (params.hide) {
  204. clearTimeout(dragTimeout);
  205. dragTimeout = nextTick(() => {
  206. el.style.opacity = 0;
  207. el.style.transitionDuration = '400ms';
  208. }, 1000);
  209. }
  210. emit('scrollbarDragEnd', e);
  211. if (params.snapOnRelease) {
  212. swiper.slideToClosest();
  213. }
  214. }
  215. function events(method) {
  216. const {
  217. scrollbar,
  218. params
  219. } = swiper;
  220. const el = scrollbar.el;
  221. if (!el) return;
  222. const target = el;
  223. const activeListener = params.passiveListeners ? {
  224. passive: false,
  225. capture: false
  226. } : false;
  227. const passiveListener = params.passiveListeners ? {
  228. passive: true,
  229. capture: false
  230. } : false;
  231. if (!target) return;
  232. const eventMethod = method === 'on' ? 'addEventListener' : 'removeEventListener';
  233. target[eventMethod]('pointerdown', onDragStart, activeListener);
  234. document[eventMethod]('pointermove', onDragMove, activeListener);
  235. document[eventMethod]('pointerup', onDragEnd, passiveListener);
  236. }
  237. function enableDraggable() {
  238. if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) return;
  239. events('on');
  240. }
  241. function disableDraggable() {
  242. if (!swiper.params.scrollbar.el || !swiper.scrollbar.el) return;
  243. events('off');
  244. }
  245. function init() {
  246. const {
  247. scrollbar,
  248. el: swiperEl
  249. } = swiper;
  250. swiper.params.scrollbar = createElementIfNotDefined(swiper, swiper.originalParams.scrollbar, swiper.params.scrollbar, {
  251. el: 'swiper-scrollbar'
  252. });
  253. const params = swiper.params.scrollbar;
  254. if (!params.el) return;
  255. let el;
  256. if (typeof params.el === 'string' && swiper.isElement) {
  257. el = swiper.el.querySelector(params.el);
  258. }
  259. if (!el && typeof params.el === 'string') {
  260. el = document.querySelectorAll(params.el);
  261. if (!el.length) return;
  262. } else if (!el) {
  263. el = params.el;
  264. }
  265. if (swiper.params.uniqueNavElements && typeof params.el === 'string' && el.length > 1 && swiperEl.querySelectorAll(params.el).length === 1) {
  266. el = swiperEl.querySelector(params.el);
  267. }
  268. if (el.length > 0) el = el[0];
  269. el.classList.add(swiper.isHorizontal() ? params.horizontalClass : params.verticalClass);
  270. let dragEl;
  271. if (el) {
  272. dragEl = el.querySelector(classesToSelector(swiper.params.scrollbar.dragClass));
  273. if (!dragEl) {
  274. dragEl = createElement('div', swiper.params.scrollbar.dragClass);
  275. el.append(dragEl);
  276. }
  277. }
  278. Object.assign(scrollbar, {
  279. el,
  280. dragEl
  281. });
  282. if (params.draggable) {
  283. enableDraggable();
  284. }
  285. if (el) {
  286. el.classList[swiper.enabled ? 'remove' : 'add'](...classesToTokens(swiper.params.scrollbar.lockClass));
  287. }
  288. }
  289. function destroy() {
  290. const params = swiper.params.scrollbar;
  291. const el = swiper.scrollbar.el;
  292. if (el) {
  293. el.classList.remove(...classesToTokens(swiper.isHorizontal() ? params.horizontalClass : params.verticalClass));
  294. }
  295. disableDraggable();
  296. }
  297. on('changeDirection', () => {
  298. if (!swiper.scrollbar || !swiper.scrollbar.el) return;
  299. const params = swiper.params.scrollbar;
  300. let {
  301. el
  302. } = swiper.scrollbar;
  303. el = makeElementsArray(el);
  304. el.forEach(subEl => {
  305. subEl.classList.remove(params.horizontalClass, params.verticalClass);
  306. subEl.classList.add(swiper.isHorizontal() ? params.horizontalClass : params.verticalClass);
  307. });
  308. });
  309. on('init', () => {
  310. if (swiper.params.scrollbar.enabled === false) {
  311. // eslint-disable-next-line
  312. disable();
  313. } else {
  314. init();
  315. updateSize();
  316. setTranslate();
  317. }
  318. });
  319. on('update resize observerUpdate lock unlock changeDirection', () => {
  320. updateSize();
  321. });
  322. on('setTranslate', () => {
  323. setTranslate();
  324. });
  325. on('setTransition', (_s, duration) => {
  326. setTransition(duration);
  327. });
  328. on('enable disable', () => {
  329. const {
  330. el
  331. } = swiper.scrollbar;
  332. if (el) {
  333. el.classList[swiper.enabled ? 'remove' : 'add'](...classesToTokens(swiper.params.scrollbar.lockClass));
  334. }
  335. });
  336. on('destroy', () => {
  337. destroy();
  338. });
  339. const enable = () => {
  340. swiper.el.classList.remove(...classesToTokens(swiper.params.scrollbar.scrollbarDisabledClass));
  341. if (swiper.scrollbar.el) {
  342. swiper.scrollbar.el.classList.remove(...classesToTokens(swiper.params.scrollbar.scrollbarDisabledClass));
  343. }
  344. init();
  345. updateSize();
  346. setTranslate();
  347. };
  348. const disable = () => {
  349. swiper.el.classList.add(...classesToTokens(swiper.params.scrollbar.scrollbarDisabledClass));
  350. if (swiper.scrollbar.el) {
  351. swiper.scrollbar.el.classList.add(...classesToTokens(swiper.params.scrollbar.scrollbarDisabledClass));
  352. }
  353. destroy();
  354. };
  355. Object.assign(swiper.scrollbar, {
  356. enable,
  357. disable,
  358. updateSize,
  359. setTranslate,
  360. init,
  361. destroy
  362. });
  363. }
  364. export { Scrollbar as default };