effect-creative.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. import effectInit from '../../shared/effect-init.js';
  2. import effectTarget from '../../shared/effect-target.js';
  3. import effectVirtualTransitionEnd from '../../shared/effect-virtual-transition-end.js';
  4. export default function EffectCreative({
  5. swiper,
  6. extendParams,
  7. on
  8. }) {
  9. extendParams({
  10. creativeEffect: {
  11. transformEl: null,
  12. limitProgress: 1,
  13. shadowPerProgress: false,
  14. progressMultiplier: 1,
  15. perspective: true,
  16. prev: {
  17. translate: [0, 0, 0],
  18. rotate: [0, 0, 0],
  19. opacity: 1,
  20. scale: 1,
  21. },
  22. next: {
  23. translate: [0, 0, 0],
  24. rotate: [0, 0, 0],
  25. opacity: 1,
  26. scale: 1,
  27. },
  28. },
  29. });
  30. const getTranslateValue = (value) => {
  31. if (typeof value === 'string') return value;
  32. return `${value}px`;
  33. };
  34. const setTranslate = () => {
  35. const {
  36. slides,
  37. $wrapperEl,
  38. slidesSizesGrid
  39. } = swiper;
  40. const params = swiper.params.creativeEffect;
  41. const {
  42. progressMultiplier: multiplier
  43. } = params;
  44. const isCenteredSlides = swiper.params.centeredSlides;
  45. if (isCenteredSlides) {
  46. const margin = slidesSizesGrid[0] / 2 - swiper.params.slidesOffsetBefore || 0;
  47. $wrapperEl.transform(`translateX(calc(50% - ${margin}px))`);
  48. }
  49. for (let i = 0; i < slides.length; i += 1) {
  50. const $slideEl = slides[i];
  51. const slideProgress = $slideEl.progress;
  52. const progress = Math.min(
  53. Math.max($slideEl.progress, -params.limitProgress),
  54. params.limitProgress,
  55. );
  56. let originalProgress = progress;
  57. if (!isCenteredSlides) {
  58. originalProgress = Math.min(
  59. Math.max($slideEl.originalProgress, -params.limitProgress),
  60. params.limitProgress,
  61. );
  62. }
  63. const offset = $slideEl.swiperSlideOffset;
  64. const t = [swiper.params.cssMode ? -offset - swiper.translate : -offset, 0, 0];
  65. const r = [0, 0, 0];
  66. let custom = false;
  67. if (!swiper.isHorizontal()) {
  68. t[1] = t[0];
  69. t[0] = 0;
  70. }
  71. let data = {
  72. translate: [0, 0, 0],
  73. rotate: [0, 0, 0],
  74. scale: 1,
  75. opacity: 1,
  76. };
  77. if (progress < 0) {
  78. data = params.next;
  79. custom = true;
  80. } else if (progress > 0) {
  81. data = params.prev;
  82. custom = true;
  83. }
  84. // set translate
  85. t.forEach((value, index) => {
  86. t[index] = `calc(${value}px + (${getTranslateValue(data.translate[index])} * ${Math.abs(
  87. progress * multiplier,
  88. )}))`;
  89. });
  90. // set rotates
  91. r.forEach((value, index) => {
  92. r[index] = data.rotate[index] * Math.abs(progress * multiplier);
  93. });
  94. // $slideEl[0].style.zIndex = -Math.abs(Math.round(slideProgress)) + slides.length;
  95. $slideEl.css({
  96. zIndex: -Math.abs(Math.round(slideProgress)) + slides.length
  97. })
  98. const translateString = t.join(', ');
  99. const rotateString = `rotateX(${r[0]}deg) rotateY(${r[1]}deg) rotateZ(${r[2]}deg)`;
  100. const scaleString =
  101. originalProgress < 0 ?
  102. `scale(${1 + (1 - data.scale) * originalProgress * multiplier})` :
  103. `scale(${1 - (1 - data.scale) * originalProgress * multiplier})`;
  104. const opacityString =
  105. originalProgress < 0 ?
  106. 1 + (1 - data.opacity) * originalProgress * multiplier :
  107. 1 - (1 - data.opacity) * originalProgress * multiplier;
  108. const transform = `translate3d(${translateString}) ${rotateString} ${scaleString}`;
  109. // Set shadows
  110. // if ((custom && data.shadow) || !custom) {
  111. // let $shadowEl = $slideEl.children('.swiper-slide-shadow');
  112. // if ($shadowEl.length === 0 && data.shadow) {
  113. // $shadowEl = createShadow(params, $slideEl);
  114. // }
  115. // if ($shadowEl.length) {
  116. // const shadowOpacity = params.shadowPerProgress
  117. // ? progress * (1 / params.limitProgress)
  118. // : progress;
  119. // $shadowEl[0].style.opacity = Math.min(Math.max(Math.abs(shadowOpacity), 0), 1);
  120. // }
  121. // }
  122. const $targetEl = effectTarget(params, $slideEl);
  123. $targetEl.transform(transform);
  124. $targetEl.css({
  125. opacity: opacityString
  126. });
  127. if (data.origin) {
  128. $targetEl.css({
  129. 'transform-origin': data.origin
  130. });
  131. }
  132. if (swiper.params.willChange) {
  133. slides[i].willChange("transform,opacity");
  134. }
  135. slides[i].addClass('swiper-slide-creative')
  136. }
  137. };
  138. const setTransition = (duration) => {
  139. const {
  140. transformEl
  141. } = swiper.params.creativeEffect;
  142. const $transitionElements = transformEl ? swiper.slides.find(transformEl) : swiper.slides;
  143. for (let i = 0; i < $transitionElements.length; i += 1) {
  144. $transitionElements[i].transition(duration);
  145. }
  146. effectVirtualTransitionEnd({
  147. swiper,
  148. duration,
  149. transformEl,
  150. allSlides: true
  151. });
  152. };
  153. effectInit({
  154. effect: 'creative',
  155. swiper,
  156. on,
  157. setTranslate,
  158. setTransition,
  159. perspective: () => swiper.params.creativeEffect.perspective,
  160. overwriteParams: () => ({
  161. watchSlidesProgress: true,
  162. virtualTranslate: !swiper.params.cssMode,
  163. }),
  164. });
  165. }