swiper.svelte 4.4 KB

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