swiper.svelte 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. <script>
  2. import {
  3. onMount,
  4. onDestroy,
  5. afterUpdate,
  6. createEventDispatcher,
  7. tick,
  8. setContext,
  9. beforeUpdate,
  10. } from 'svelte';
  11. import { getParams } from './get-params.js';
  12. import { initSwiper, mountSwiper } from './init-swiper.js';
  13. import {
  14. needsScrollbar,
  15. needsNavigation,
  16. needsPagination,
  17. uniqueClasses,
  18. extend,
  19. } from './utils.js';
  20. import { getChangedParams } from './get-changed-params.js';
  21. import { updateSwiper } from './update-swiper.js';
  22. const dispatch = createEventDispatcher();
  23. let className = undefined;
  24. export { className as class };
  25. let containerClasses = 'swiper';
  26. let breakpointChanged = false;
  27. let swiperInstance = null;
  28. let oldPassedParams = null;
  29. let paramsData;
  30. let swiperParams;
  31. let passedParams;
  32. let restProps;
  33. let swiperEl = null;
  34. let prevEl = null;
  35. let nextEl = null;
  36. let scrollbarEl = null;
  37. let paginationEl = null;
  38. let virtualData = { slides: [] };
  39. export function swiper() {
  40. return swiperInstance;
  41. }
  42. const setVirtualData = (data) => {
  43. virtualData = data;
  44. tick().then(() => {
  45. swiperInstance.$wrapperEl.children('.swiper-slide').each((el) => {
  46. if (el.onSwiper) el.onSwiper(swiperInstance);
  47. });
  48. swiperInstance.updateSlides();
  49. swiperInstance.updateProgress();
  50. swiperInstance.updateSlidesClasses();
  51. if (swiperInstance.lazy && swiperInstance.params.lazy.enabled) {
  52. swiperInstance.lazy.load();
  53. }
  54. });
  55. };
  56. const calcParams = () => {
  57. paramsData = getParams($$restProps);
  58. swiperParams = paramsData.params;
  59. passedParams = paramsData.passedParams;
  60. restProps = paramsData.rest;
  61. };
  62. calcParams();
  63. oldPassedParams = passedParams;
  64. const onBeforeBreakpoint = () => {
  65. breakpointChanged = true;
  66. };
  67. swiperParams.onAny = (event, ...args) => {
  68. dispatch(event, [args]);
  69. };
  70. Object.assign(swiperParams.on, {
  71. _beforeBreakpoint: onBeforeBreakpoint,
  72. _containerClasses(_swiper, classes) {
  73. containerClasses = classes;
  74. },
  75. });
  76. swiperInstance = initSwiper(swiperParams);
  77. setContext('swiper', swiperInstance);
  78. if (swiperInstance.virtual && swiperInstance.params.virtual.enabled) {
  79. const extendWith = {
  80. cache: false,
  81. renderExternal: (data) => {
  82. setVirtualData(data);
  83. if (swiperParams.virtual && swiperParams.virtual.renderExternal) {
  84. swiperParams.virtual.renderExternal(data);
  85. }
  86. },
  87. renderExternalUpdate: false,
  88. };
  89. extend(swiperInstance.params.virtual, extendWith);
  90. extend(swiperInstance.originalParams.virtual, extendWith);
  91. }
  92. onMount(() => {
  93. if (!swiperEl) return;
  94. mountSwiper(
  95. {
  96. el: swiperEl,
  97. nextEl: nextEl,
  98. prevEl: prevEl,
  99. paginationEl: paginationEl,
  100. scrollbarEl: scrollbarEl,
  101. swiper: swiperInstance,
  102. },
  103. swiperParams,
  104. );
  105. dispatch('swiper', [swiperInstance]);
  106. if (swiperParams.virtual) return;
  107. swiperInstance.slides.each((el) => {
  108. if (el.onSwiper) el.onSwiper(swiperInstance);
  109. });
  110. });
  111. afterUpdate(() => {
  112. if (!swiperInstance) return;
  113. calcParams();
  114. const changedParams = getChangedParams(passedParams, oldPassedParams);
  115. if (
  116. (changedParams.length || breakpointChanged) &&
  117. swiperInstance &&
  118. !swiperInstance.destroyed
  119. ) {
  120. updateSwiper({
  121. swiper: swiperInstance,
  122. passedParams,
  123. changedParams,
  124. nextEl,
  125. prevEl,
  126. scrollbarEl,
  127. paginationEl,
  128. });
  129. }
  130. breakpointChanged = false;
  131. oldPassedParams = passedParams;
  132. });
  133. onDestroy(() => {
  134. // eslint-disable-next-line
  135. if (typeof window !== 'undefined' && swiperInstance && !swiperInstance.destroyed) {
  136. swiperInstance.destroy(true, false);
  137. }
  138. });
  139. </script>
  140. <div
  141. bind:this={swiperEl}
  142. class={uniqueClasses(`${containerClasses}${className ? ` ${className}` : ''}`)}
  143. {...restProps}
  144. >
  145. <slot name="container-start" />
  146. {#if needsNavigation(swiperParams)}
  147. <div bind:this={prevEl} class="swiper-button-prev" />
  148. <div bind:this={nextEl} class="swiper-button-next" />
  149. {/if}
  150. {#if needsScrollbar(swiperParams)}
  151. <div bind:this={scrollbarEl} class="swiper-scrollbar" />
  152. {/if}
  153. {#if needsPagination(swiperParams)}
  154. <div bind:this={paginationEl} class="swiper-pagination" />
  155. {/if}
  156. <div class="swiper-wrapper">
  157. <slot name="wrapper-start" />
  158. <slot {virtualData} />
  159. <slot name="wrapper-end" />
  160. </div>
  161. <slot name="container-end" />
  162. </div>