utils.js 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. import { getWindow, getDocument } from 'ssr-window';
  2. function deleteProps(obj) {
  3. const object = obj;
  4. Object.keys(object).forEach(key => {
  5. try {
  6. object[key] = null;
  7. } catch (e) {
  8. // no getter for object
  9. }
  10. try {
  11. delete object[key];
  12. } catch (e) {
  13. // something got wrong
  14. }
  15. });
  16. }
  17. function nextTick(callback, delay = 0) {
  18. return setTimeout(callback, delay);
  19. }
  20. function now() {
  21. return Date.now();
  22. }
  23. function getComputedStyle(el) {
  24. const window = getWindow();
  25. let style;
  26. if (window.getComputedStyle) {
  27. style = window.getComputedStyle(el, null);
  28. }
  29. if (!style && el.currentStyle) {
  30. style = el.currentStyle;
  31. }
  32. if (!style) {
  33. style = el.style;
  34. }
  35. return style;
  36. }
  37. function getTranslate(el, axis = 'x') {
  38. const window = getWindow();
  39. let matrix;
  40. let curTransform;
  41. let transformMatrix;
  42. const curStyle = getComputedStyle(el, null);
  43. if (window.WebKitCSSMatrix) {
  44. curTransform = curStyle.transform || curStyle.webkitTransform;
  45. if (curTransform.split(',').length > 6) {
  46. curTransform = curTransform.split(', ').map(a => a.replace(',', '.')).join(', ');
  47. }
  48. // Some old versions of Webkit choke when 'none' is passed; pass
  49. // empty string instead in this case
  50. transformMatrix = new window.WebKitCSSMatrix(curTransform === 'none' ? '' : curTransform);
  51. } else {
  52. transformMatrix = curStyle.MozTransform || curStyle.OTransform || curStyle.MsTransform || curStyle.msTransform || curStyle.transform || curStyle.getPropertyValue('transform').replace('translate(', 'matrix(1, 0, 0, 1,');
  53. matrix = transformMatrix.toString().split(',');
  54. }
  55. if (axis === 'x') {
  56. // Latest Chrome and webkits Fix
  57. if (window.WebKitCSSMatrix) curTransform = transformMatrix.m41;
  58. // Crazy IE10 Matrix
  59. else if (matrix.length === 16) curTransform = parseFloat(matrix[12]);
  60. // Normal Browsers
  61. else curTransform = parseFloat(matrix[4]);
  62. }
  63. if (axis === 'y') {
  64. // Latest Chrome and webkits Fix
  65. if (window.WebKitCSSMatrix) curTransform = transformMatrix.m42;
  66. // Crazy IE10 Matrix
  67. else if (matrix.length === 16) curTransform = parseFloat(matrix[13]);
  68. // Normal Browsers
  69. else curTransform = parseFloat(matrix[5]);
  70. }
  71. return curTransform || 0;
  72. }
  73. function isObject(o) {
  74. return typeof o === 'object' && o !== null && o.constructor && Object.prototype.toString.call(o).slice(8, -1) === 'Object';
  75. }
  76. function isNode(node) {
  77. // eslint-disable-next-line
  78. if (typeof window !== 'undefined' && typeof window.HTMLElement !== 'undefined') {
  79. return node instanceof HTMLElement;
  80. }
  81. return node && (node.nodeType === 1 || node.nodeType === 11);
  82. }
  83. function extend(...args) {
  84. const to = Object(args[0]);
  85. const noExtend = ['__proto__', 'constructor', 'prototype'];
  86. for (let i = 1; i < args.length; i += 1) {
  87. const nextSource = args[i];
  88. if (nextSource !== undefined && nextSource !== null && !isNode(nextSource)) {
  89. const keysArray = Object.keys(Object(nextSource)).filter(key => noExtend.indexOf(key) < 0);
  90. for (let nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex += 1) {
  91. const nextKey = keysArray[nextIndex];
  92. const desc = Object.getOwnPropertyDescriptor(nextSource, nextKey);
  93. if (desc !== undefined && desc.enumerable) {
  94. if (isObject(to[nextKey]) && isObject(nextSource[nextKey])) {
  95. if (nextSource[nextKey].__swiper__) {
  96. to[nextKey] = nextSource[nextKey];
  97. } else {
  98. extend(to[nextKey], nextSource[nextKey]);
  99. }
  100. } else if (!isObject(to[nextKey]) && isObject(nextSource[nextKey])) {
  101. to[nextKey] = {};
  102. if (nextSource[nextKey].__swiper__) {
  103. to[nextKey] = nextSource[nextKey];
  104. } else {
  105. extend(to[nextKey], nextSource[nextKey]);
  106. }
  107. } else {
  108. to[nextKey] = nextSource[nextKey];
  109. }
  110. }
  111. }
  112. }
  113. }
  114. return to;
  115. }
  116. function setCSSProperty(el, varName, varValue) {
  117. el.style.setProperty(varName, varValue);
  118. }
  119. function animateCSSModeScroll({
  120. swiper,
  121. targetPosition,
  122. side
  123. }) {
  124. const window = getWindow();
  125. const startPosition = -swiper.translate;
  126. let startTime = null;
  127. let time;
  128. const duration = swiper.params.speed;
  129. swiper.wrapperEl.style.scrollSnapType = 'none';
  130. window.cancelAnimationFrame(swiper.cssModeFrameID);
  131. const dir = targetPosition > startPosition ? 'next' : 'prev';
  132. const isOutOfBound = (current, target) => {
  133. return dir === 'next' && current >= target || dir === 'prev' && current <= target;
  134. };
  135. const animate = () => {
  136. time = new Date().getTime();
  137. if (startTime === null) {
  138. startTime = time;
  139. }
  140. const progress = Math.max(Math.min((time - startTime) / duration, 1), 0);
  141. const easeProgress = 0.5 - Math.cos(progress * Math.PI) / 2;
  142. let currentPosition = startPosition + easeProgress * (targetPosition - startPosition);
  143. if (isOutOfBound(currentPosition, targetPosition)) {
  144. currentPosition = targetPosition;
  145. }
  146. swiper.wrapperEl.scrollTo({
  147. [side]: currentPosition
  148. });
  149. if (isOutOfBound(currentPosition, targetPosition)) {
  150. swiper.wrapperEl.style.overflow = 'hidden';
  151. swiper.wrapperEl.style.scrollSnapType = '';
  152. setTimeout(() => {
  153. swiper.wrapperEl.style.overflow = '';
  154. swiper.wrapperEl.scrollTo({
  155. [side]: currentPosition
  156. });
  157. });
  158. window.cancelAnimationFrame(swiper.cssModeFrameID);
  159. return;
  160. }
  161. swiper.cssModeFrameID = window.requestAnimationFrame(animate);
  162. };
  163. animate();
  164. }
  165. function getSlideTransformEl(slideEl) {
  166. return slideEl.querySelector('.swiper-slide-transform') || slideEl.shadowEl && slideEl.shadowEl.querySelector('.swiper-slide-transform') || slideEl;
  167. }
  168. function findElementsInElements(elements = [], selector = '') {
  169. const found = [];
  170. elements.forEach(el => {
  171. found.push(...el.querySelectorAll(selector));
  172. });
  173. return found;
  174. }
  175. function elementChildren(element, selector = '') {
  176. return [...element.children].filter(el => el.matches(selector));
  177. }
  178. function createElement(tag, classes = []) {
  179. const el = document.createElement(tag);
  180. el.classList.add(...(Array.isArray(classes) ? classes : [classes]));
  181. return el;
  182. }
  183. function elementOffset(el) {
  184. const window = getWindow();
  185. const document = getDocument();
  186. const box = el.getBoundingClientRect();
  187. const body = document.body;
  188. const clientTop = el.clientTop || body.clientTop || 0;
  189. const clientLeft = el.clientLeft || body.clientLeft || 0;
  190. const scrollTop = el === window ? window.scrollY : el.scrollTop;
  191. const scrollLeft = el === window ? window.scrollX : el.scrollLeft;
  192. return {
  193. top: box.top + scrollTop - clientTop,
  194. left: box.left + scrollLeft - clientLeft
  195. };
  196. }
  197. function elementPrevAll(el, selector) {
  198. const prevEls = [];
  199. while (el.previousElementSibling) {
  200. const prev = el.previousElementSibling; // eslint-disable-line
  201. if (selector) {
  202. if (prev.matches(selector)) prevEls.push(prev);
  203. } else prevEls.push(prev);
  204. el = prev;
  205. }
  206. return prevEls;
  207. }
  208. function elementNextAll(el, selector) {
  209. const nextEls = [];
  210. while (el.nextElementSibling) {
  211. const next = el.nextElementSibling; // eslint-disable-line
  212. if (selector) {
  213. if (next.matches(selector)) nextEls.push(next);
  214. } else nextEls.push(next);
  215. el = next;
  216. }
  217. return nextEls;
  218. }
  219. function elementStyle(el, prop) {
  220. const window = getWindow();
  221. return window.getComputedStyle(el, null).getPropertyValue(prop);
  222. }
  223. function elementIndex(el) {
  224. let child = el;
  225. let i;
  226. if (child) {
  227. i = 0;
  228. // eslint-disable-next-line
  229. while ((child = child.previousSibling) !== null) {
  230. if (child.nodeType === 1) i += 1;
  231. }
  232. return i;
  233. }
  234. return undefined;
  235. }
  236. function elementParents(el, selector) {
  237. const parents = []; // eslint-disable-line
  238. let parent = el.parentElement; // eslint-disable-line
  239. while (parent) {
  240. if (selector) {
  241. if (parent.matches(selector)) parents.push(parent);
  242. } else {
  243. parents.push(parent);
  244. }
  245. parent = parent.parentElement;
  246. }
  247. return parents;
  248. }
  249. function elementTransitionEnd(el, callback) {
  250. function fireCallBack(e) {
  251. if (e.target !== el) return;
  252. callback.call(el, e);
  253. el.removeEventListener('transitionend', fireCallBack);
  254. }
  255. if (callback) {
  256. el.addEventListener('transitionend', fireCallBack);
  257. }
  258. }
  259. function elementOuterSize(el, size, includeMargins) {
  260. const window = getWindow();
  261. if (includeMargins) {
  262. return el[size === 'width' ? 'offsetWidth' : 'offsetHeight'] + parseFloat(window.getComputedStyle(el, null).getPropertyValue(size === 'width' ? 'margin-right' : 'margin-top')) + parseFloat(window.getComputedStyle(el, null).getPropertyValue(size === 'width' ? 'margin-left' : 'margin-bottom'));
  263. }
  264. return el.offsetWidth;
  265. }
  266. export { animateCSSModeScroll, deleteProps, nextTick, now, getTranslate, isObject, extend, getComputedStyle, setCSSProperty, getSlideTransformEl,
  267. // dom
  268. findElementsInElements, createElement, elementChildren, elementOffset, elementPrevAll, elementNextAll, elementStyle, elementIndex, elementParents, elementTransitionEnd, elementOuterSize };