zoom.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  1. import { getWindow } from 'ssr-window';
  2. import $ from '../../shared/dom.js';
  3. import { getTranslate } from '../../shared/utils.js';
  4. export default function Zoom(_ref) {
  5. let {
  6. swiper,
  7. extendParams,
  8. on,
  9. emit
  10. } = _ref;
  11. const window = getWindow();
  12. extendParams({
  13. zoom: {
  14. enabled: false,
  15. maxRatio: 3,
  16. minRatio: 1,
  17. toggle: true,
  18. containerClass: 'swiper-zoom-container',
  19. zoomedSlideClass: 'swiper-slide-zoomed'
  20. }
  21. });
  22. swiper.zoom = {
  23. enabled: false
  24. };
  25. let currentScale = 1;
  26. let isScaling = false;
  27. let gesturesEnabled;
  28. let fakeGestureTouched;
  29. let fakeGestureMoved;
  30. const gesture = {
  31. $slideEl: undefined,
  32. slideWidth: undefined,
  33. slideHeight: undefined,
  34. $imageEl: undefined,
  35. $imageWrapEl: undefined,
  36. maxRatio: 3
  37. };
  38. const image = {
  39. isTouched: undefined,
  40. isMoved: undefined,
  41. currentX: undefined,
  42. currentY: undefined,
  43. minX: undefined,
  44. minY: undefined,
  45. maxX: undefined,
  46. maxY: undefined,
  47. width: undefined,
  48. height: undefined,
  49. startX: undefined,
  50. startY: undefined,
  51. touchesStart: {},
  52. touchesCurrent: {}
  53. };
  54. const velocity = {
  55. x: undefined,
  56. y: undefined,
  57. prevPositionX: undefined,
  58. prevPositionY: undefined,
  59. prevTime: undefined
  60. };
  61. let scale = 1;
  62. Object.defineProperty(swiper.zoom, 'scale', {
  63. get() {
  64. return scale;
  65. },
  66. set(value) {
  67. if (scale !== value) {
  68. const imageEl = gesture.$imageEl ? gesture.$imageEl[0] : undefined;
  69. const slideEl = gesture.$slideEl ? gesture.$slideEl[0] : undefined;
  70. emit('zoomChange', value, imageEl, slideEl);
  71. }
  72. scale = value;
  73. }
  74. });
  75. function getDistanceBetweenTouches(e) {
  76. if (e.targetTouches.length < 2) return 1;
  77. const x1 = e.targetTouches[0].pageX;
  78. const y1 = e.targetTouches[0].pageY;
  79. const x2 = e.targetTouches[1].pageX;
  80. const y2 = e.targetTouches[1].pageY;
  81. const distance = Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);
  82. return distance;
  83. } // Events
  84. function onGestureStart(e) {
  85. const support = swiper.support;
  86. const params = swiper.params.zoom;
  87. fakeGestureTouched = false;
  88. fakeGestureMoved = false;
  89. if (!support.gestures) {
  90. if (e.type !== 'touchstart' || e.type === 'touchstart' && e.targetTouches.length < 2) {
  91. return;
  92. }
  93. fakeGestureTouched = true;
  94. gesture.scaleStart = getDistanceBetweenTouches(e);
  95. }
  96. if (!gesture.$slideEl || !gesture.$slideEl.length) {
  97. gesture.$slideEl = $(e.target).closest(`.${swiper.params.slideClass}`);
  98. if (gesture.$slideEl.length === 0) gesture.$slideEl = swiper.slides.eq(swiper.activeIndex);
  99. gesture.$imageEl = gesture.$slideEl.find(`.${params.containerClass}`).eq(0).find('picture, img, svg, canvas, .swiper-zoom-target').eq(0);
  100. gesture.$imageWrapEl = gesture.$imageEl.parent(`.${params.containerClass}`);
  101. gesture.maxRatio = gesture.$imageWrapEl.attr('data-swiper-zoom') || params.maxRatio;
  102. if (gesture.$imageWrapEl.length === 0) {
  103. gesture.$imageEl = undefined;
  104. return;
  105. }
  106. }
  107. if (gesture.$imageEl) {
  108. gesture.$imageEl.transition(0);
  109. }
  110. isScaling = true;
  111. }
  112. function onGestureChange(e) {
  113. const support = swiper.support;
  114. const params = swiper.params.zoom;
  115. const zoom = swiper.zoom;
  116. if (!support.gestures) {
  117. if (e.type !== 'touchmove' || e.type === 'touchmove' && e.targetTouches.length < 2) {
  118. return;
  119. }
  120. fakeGestureMoved = true;
  121. gesture.scaleMove = getDistanceBetweenTouches(e);
  122. }
  123. if (!gesture.$imageEl || gesture.$imageEl.length === 0) {
  124. if (e.type === 'gesturechange') onGestureStart(e);
  125. return;
  126. }
  127. if (support.gestures) {
  128. zoom.scale = e.scale * currentScale;
  129. } else {
  130. zoom.scale = gesture.scaleMove / gesture.scaleStart * currentScale;
  131. }
  132. if (zoom.scale > gesture.maxRatio) {
  133. zoom.scale = gesture.maxRatio - 1 + (zoom.scale - gesture.maxRatio + 1) ** 0.5;
  134. }
  135. if (zoom.scale < params.minRatio) {
  136. zoom.scale = params.minRatio + 1 - (params.minRatio - zoom.scale + 1) ** 0.5;
  137. }
  138. gesture.$imageEl.transform(`translate3d(0,0,0) scale(${zoom.scale})`);
  139. }
  140. function onGestureEnd(e) {
  141. const device = swiper.device;
  142. const support = swiper.support;
  143. const params = swiper.params.zoom;
  144. const zoom = swiper.zoom;
  145. if (!support.gestures) {
  146. if (!fakeGestureTouched || !fakeGestureMoved) {
  147. return;
  148. }
  149. if (e.type !== 'touchend' || e.type === 'touchend' && e.changedTouches.length < 2 && !device.android) {
  150. return;
  151. }
  152. fakeGestureTouched = false;
  153. fakeGestureMoved = false;
  154. }
  155. if (!gesture.$imageEl || gesture.$imageEl.length === 0) return;
  156. zoom.scale = Math.max(Math.min(zoom.scale, gesture.maxRatio), params.minRatio);
  157. gesture.$imageEl.transition(swiper.params.speed).transform(`translate3d(0,0,0) scale(${zoom.scale})`);
  158. currentScale = zoom.scale;
  159. isScaling = false;
  160. if (zoom.scale === 1) gesture.$slideEl = undefined;
  161. }
  162. function onTouchStart(e) {
  163. const device = swiper.device;
  164. if (!gesture.$imageEl || gesture.$imageEl.length === 0) return;
  165. if (image.isTouched) return;
  166. if (device.android && e.cancelable) e.preventDefault();
  167. image.isTouched = true;
  168. image.touchesStart.x = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;
  169. image.touchesStart.y = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
  170. }
  171. function onTouchMove(e) {
  172. const zoom = swiper.zoom;
  173. if (!gesture.$imageEl || gesture.$imageEl.length === 0) return;
  174. swiper.allowClick = false;
  175. if (!image.isTouched || !gesture.$slideEl) return;
  176. if (!image.isMoved) {
  177. image.width = gesture.$imageEl[0].offsetWidth;
  178. image.height = gesture.$imageEl[0].offsetHeight;
  179. image.startX = getTranslate(gesture.$imageWrapEl[0], 'x') || 0;
  180. image.startY = getTranslate(gesture.$imageWrapEl[0], 'y') || 0;
  181. gesture.slideWidth = gesture.$slideEl[0].offsetWidth;
  182. gesture.slideHeight = gesture.$slideEl[0].offsetHeight;
  183. gesture.$imageWrapEl.transition(0);
  184. } // Define if we need image drag
  185. const scaledWidth = image.width * zoom.scale;
  186. const scaledHeight = image.height * zoom.scale;
  187. if (scaledWidth < gesture.slideWidth && scaledHeight < gesture.slideHeight) return;
  188. image.minX = Math.min(gesture.slideWidth / 2 - scaledWidth / 2, 0);
  189. image.maxX = -image.minX;
  190. image.minY = Math.min(gesture.slideHeight / 2 - scaledHeight / 2, 0);
  191. image.maxY = -image.minY;
  192. image.touchesCurrent.x = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;
  193. image.touchesCurrent.y = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
  194. if (!image.isMoved && !isScaling) {
  195. if (swiper.isHorizontal() && (Math.floor(image.minX) === Math.floor(image.startX) && image.touchesCurrent.x < image.touchesStart.x || Math.floor(image.maxX) === Math.floor(image.startX) && image.touchesCurrent.x > image.touchesStart.x)) {
  196. image.isTouched = false;
  197. return;
  198. }
  199. if (!swiper.isHorizontal() && (Math.floor(image.minY) === Math.floor(image.startY) && image.touchesCurrent.y < image.touchesStart.y || Math.floor(image.maxY) === Math.floor(image.startY) && image.touchesCurrent.y > image.touchesStart.y)) {
  200. image.isTouched = false;
  201. return;
  202. }
  203. }
  204. if (e.cancelable) {
  205. e.preventDefault();
  206. }
  207. e.stopPropagation();
  208. image.isMoved = true;
  209. image.currentX = image.touchesCurrent.x - image.touchesStart.x + image.startX;
  210. image.currentY = image.touchesCurrent.y - image.touchesStart.y + image.startY;
  211. if (image.currentX < image.minX) {
  212. image.currentX = image.minX + 1 - (image.minX - image.currentX + 1) ** 0.8;
  213. }
  214. if (image.currentX > image.maxX) {
  215. image.currentX = image.maxX - 1 + (image.currentX - image.maxX + 1) ** 0.8;
  216. }
  217. if (image.currentY < image.minY) {
  218. image.currentY = image.minY + 1 - (image.minY - image.currentY + 1) ** 0.8;
  219. }
  220. if (image.currentY > image.maxY) {
  221. image.currentY = image.maxY - 1 + (image.currentY - image.maxY + 1) ** 0.8;
  222. } // Velocity
  223. if (!velocity.prevPositionX) velocity.prevPositionX = image.touchesCurrent.x;
  224. if (!velocity.prevPositionY) velocity.prevPositionY = image.touchesCurrent.y;
  225. if (!velocity.prevTime) velocity.prevTime = Date.now();
  226. velocity.x = (image.touchesCurrent.x - velocity.prevPositionX) / (Date.now() - velocity.prevTime) / 2;
  227. velocity.y = (image.touchesCurrent.y - velocity.prevPositionY) / (Date.now() - velocity.prevTime) / 2;
  228. if (Math.abs(image.touchesCurrent.x - velocity.prevPositionX) < 2) velocity.x = 0;
  229. if (Math.abs(image.touchesCurrent.y - velocity.prevPositionY) < 2) velocity.y = 0;
  230. velocity.prevPositionX = image.touchesCurrent.x;
  231. velocity.prevPositionY = image.touchesCurrent.y;
  232. velocity.prevTime = Date.now();
  233. gesture.$imageWrapEl.transform(`translate3d(${image.currentX}px, ${image.currentY}px,0)`);
  234. }
  235. function onTouchEnd() {
  236. const zoom = swiper.zoom;
  237. if (!gesture.$imageEl || gesture.$imageEl.length === 0) return;
  238. if (!image.isTouched || !image.isMoved) {
  239. image.isTouched = false;
  240. image.isMoved = false;
  241. return;
  242. }
  243. image.isTouched = false;
  244. image.isMoved = false;
  245. let momentumDurationX = 300;
  246. let momentumDurationY = 300;
  247. const momentumDistanceX = velocity.x * momentumDurationX;
  248. const newPositionX = image.currentX + momentumDistanceX;
  249. const momentumDistanceY = velocity.y * momentumDurationY;
  250. const newPositionY = image.currentY + momentumDistanceY; // Fix duration
  251. if (velocity.x !== 0) momentumDurationX = Math.abs((newPositionX - image.currentX) / velocity.x);
  252. if (velocity.y !== 0) momentumDurationY = Math.abs((newPositionY - image.currentY) / velocity.y);
  253. const momentumDuration = Math.max(momentumDurationX, momentumDurationY);
  254. image.currentX = newPositionX;
  255. image.currentY = newPositionY; // Define if we need image drag
  256. const scaledWidth = image.width * zoom.scale;
  257. const scaledHeight = image.height * zoom.scale;
  258. image.minX = Math.min(gesture.slideWidth / 2 - scaledWidth / 2, 0);
  259. image.maxX = -image.minX;
  260. image.minY = Math.min(gesture.slideHeight / 2 - scaledHeight / 2, 0);
  261. image.maxY = -image.minY;
  262. image.currentX = Math.max(Math.min(image.currentX, image.maxX), image.minX);
  263. image.currentY = Math.max(Math.min(image.currentY, image.maxY), image.minY);
  264. gesture.$imageWrapEl.transition(momentumDuration).transform(`translate3d(${image.currentX}px, ${image.currentY}px,0)`);
  265. }
  266. function onTransitionEnd() {
  267. const zoom = swiper.zoom;
  268. if (gesture.$slideEl && swiper.previousIndex !== swiper.activeIndex) {
  269. if (gesture.$imageEl) {
  270. gesture.$imageEl.transform('translate3d(0,0,0) scale(1)');
  271. }
  272. if (gesture.$imageWrapEl) {
  273. gesture.$imageWrapEl.transform('translate3d(0,0,0)');
  274. }
  275. zoom.scale = 1;
  276. currentScale = 1;
  277. gesture.$slideEl = undefined;
  278. gesture.$imageEl = undefined;
  279. gesture.$imageWrapEl = undefined;
  280. }
  281. }
  282. function zoomIn(e) {
  283. const zoom = swiper.zoom;
  284. const params = swiper.params.zoom;
  285. if (!gesture.$slideEl) {
  286. if (e && e.target) {
  287. gesture.$slideEl = $(e.target).closest(`.${swiper.params.slideClass}`);
  288. }
  289. if (!gesture.$slideEl) {
  290. if (swiper.params.virtual && swiper.params.virtual.enabled && swiper.virtual) {
  291. gesture.$slideEl = swiper.$wrapperEl.children(`.${swiper.params.slideActiveClass}`);
  292. } else {
  293. gesture.$slideEl = swiper.slides.eq(swiper.activeIndex);
  294. }
  295. }
  296. gesture.$imageEl = gesture.$slideEl.find(`.${params.containerClass}`).eq(0).find('picture, img, svg, canvas, .swiper-zoom-target').eq(0);
  297. gesture.$imageWrapEl = gesture.$imageEl.parent(`.${params.containerClass}`);
  298. }
  299. if (!gesture.$imageEl || gesture.$imageEl.length === 0 || !gesture.$imageWrapEl || gesture.$imageWrapEl.length === 0) return;
  300. if (swiper.params.cssMode) {
  301. swiper.wrapperEl.style.overflow = 'hidden';
  302. swiper.wrapperEl.style.touchAction = 'none';
  303. }
  304. gesture.$slideEl.addClass(`${params.zoomedSlideClass}`);
  305. let touchX;
  306. let touchY;
  307. let offsetX;
  308. let offsetY;
  309. let diffX;
  310. let diffY;
  311. let translateX;
  312. let translateY;
  313. let imageWidth;
  314. let imageHeight;
  315. let scaledWidth;
  316. let scaledHeight;
  317. let translateMinX;
  318. let translateMinY;
  319. let translateMaxX;
  320. let translateMaxY;
  321. let slideWidth;
  322. let slideHeight;
  323. if (typeof image.touchesStart.x === 'undefined' && e) {
  324. touchX = e.type === 'touchend' ? e.changedTouches[0].pageX : e.pageX;
  325. touchY = e.type === 'touchend' ? e.changedTouches[0].pageY : e.pageY;
  326. } else {
  327. touchX = image.touchesStart.x;
  328. touchY = image.touchesStart.y;
  329. }
  330. zoom.scale = gesture.$imageWrapEl.attr('data-swiper-zoom') || params.maxRatio;
  331. currentScale = gesture.$imageWrapEl.attr('data-swiper-zoom') || params.maxRatio;
  332. if (e) {
  333. slideWidth = gesture.$slideEl[0].offsetWidth;
  334. slideHeight = gesture.$slideEl[0].offsetHeight;
  335. offsetX = gesture.$slideEl.offset().left + window.scrollX;
  336. offsetY = gesture.$slideEl.offset().top + window.scrollY;
  337. diffX = offsetX + slideWidth / 2 - touchX;
  338. diffY = offsetY + slideHeight / 2 - touchY;
  339. imageWidth = gesture.$imageEl[0].offsetWidth;
  340. imageHeight = gesture.$imageEl[0].offsetHeight;
  341. scaledWidth = imageWidth * zoom.scale;
  342. scaledHeight = imageHeight * zoom.scale;
  343. translateMinX = Math.min(slideWidth / 2 - scaledWidth / 2, 0);
  344. translateMinY = Math.min(slideHeight / 2 - scaledHeight / 2, 0);
  345. translateMaxX = -translateMinX;
  346. translateMaxY = -translateMinY;
  347. translateX = diffX * zoom.scale;
  348. translateY = diffY * zoom.scale;
  349. if (translateX < translateMinX) {
  350. translateX = translateMinX;
  351. }
  352. if (translateX > translateMaxX) {
  353. translateX = translateMaxX;
  354. }
  355. if (translateY < translateMinY) {
  356. translateY = translateMinY;
  357. }
  358. if (translateY > translateMaxY) {
  359. translateY = translateMaxY;
  360. }
  361. } else {
  362. translateX = 0;
  363. translateY = 0;
  364. }
  365. gesture.$imageWrapEl.transition(300).transform(`translate3d(${translateX}px, ${translateY}px,0)`);
  366. gesture.$imageEl.transition(300).transform(`translate3d(0,0,0) scale(${zoom.scale})`);
  367. }
  368. function zoomOut() {
  369. const zoom = swiper.zoom;
  370. const params = swiper.params.zoom;
  371. if (!gesture.$slideEl) {
  372. if (swiper.params.virtual && swiper.params.virtual.enabled && swiper.virtual) {
  373. gesture.$slideEl = swiper.$wrapperEl.children(`.${swiper.params.slideActiveClass}`);
  374. } else {
  375. gesture.$slideEl = swiper.slides.eq(swiper.activeIndex);
  376. }
  377. gesture.$imageEl = gesture.$slideEl.find(`.${params.containerClass}`).eq(0).find('picture, img, svg, canvas, .swiper-zoom-target').eq(0);
  378. gesture.$imageWrapEl = gesture.$imageEl.parent(`.${params.containerClass}`);
  379. }
  380. if (!gesture.$imageEl || gesture.$imageEl.length === 0 || !gesture.$imageWrapEl || gesture.$imageWrapEl.length === 0) return;
  381. if (swiper.params.cssMode) {
  382. swiper.wrapperEl.style.overflow = '';
  383. swiper.wrapperEl.style.touchAction = '';
  384. }
  385. zoom.scale = 1;
  386. currentScale = 1;
  387. gesture.$imageWrapEl.transition(300).transform('translate3d(0,0,0)');
  388. gesture.$imageEl.transition(300).transform('translate3d(0,0,0) scale(1)');
  389. gesture.$slideEl.removeClass(`${params.zoomedSlideClass}`);
  390. gesture.$slideEl = undefined;
  391. } // Toggle Zoom
  392. function zoomToggle(e) {
  393. const zoom = swiper.zoom;
  394. if (zoom.scale && zoom.scale !== 1) {
  395. // Zoom Out
  396. zoomOut();
  397. } else {
  398. // Zoom In
  399. zoomIn(e);
  400. }
  401. }
  402. function getListeners() {
  403. const support = swiper.support;
  404. const passiveListener = swiper.touchEvents.start === 'touchstart' && support.passiveListener && swiper.params.passiveListeners ? {
  405. passive: true,
  406. capture: false
  407. } : false;
  408. const activeListenerWithCapture = support.passiveListener ? {
  409. passive: false,
  410. capture: true
  411. } : true;
  412. return {
  413. passiveListener,
  414. activeListenerWithCapture
  415. };
  416. }
  417. function getSlideSelector() {
  418. return `.${swiper.params.slideClass}`;
  419. }
  420. function toggleGestures(method) {
  421. const {
  422. passiveListener
  423. } = getListeners();
  424. const slideSelector = getSlideSelector();
  425. swiper.$wrapperEl[method]('gesturestart', slideSelector, onGestureStart, passiveListener);
  426. swiper.$wrapperEl[method]('gesturechange', slideSelector, onGestureChange, passiveListener);
  427. swiper.$wrapperEl[method]('gestureend', slideSelector, onGestureEnd, passiveListener);
  428. }
  429. function enableGestures() {
  430. if (gesturesEnabled) return;
  431. gesturesEnabled = true;
  432. toggleGestures('on');
  433. }
  434. function disableGestures() {
  435. if (!gesturesEnabled) return;
  436. gesturesEnabled = false;
  437. toggleGestures('off');
  438. } // Attach/Detach Events
  439. function enable() {
  440. const zoom = swiper.zoom;
  441. if (zoom.enabled) return;
  442. zoom.enabled = true;
  443. const support = swiper.support;
  444. const {
  445. passiveListener,
  446. activeListenerWithCapture
  447. } = getListeners();
  448. const slideSelector = getSlideSelector(); // Scale image
  449. if (support.gestures) {
  450. swiper.$wrapperEl.on(swiper.touchEvents.start, enableGestures, passiveListener);
  451. swiper.$wrapperEl.on(swiper.touchEvents.end, disableGestures, passiveListener);
  452. } else if (swiper.touchEvents.start === 'touchstart') {
  453. swiper.$wrapperEl.on(swiper.touchEvents.start, slideSelector, onGestureStart, passiveListener);
  454. swiper.$wrapperEl.on(swiper.touchEvents.move, slideSelector, onGestureChange, activeListenerWithCapture);
  455. swiper.$wrapperEl.on(swiper.touchEvents.end, slideSelector, onGestureEnd, passiveListener);
  456. if (swiper.touchEvents.cancel) {
  457. swiper.$wrapperEl.on(swiper.touchEvents.cancel, slideSelector, onGestureEnd, passiveListener);
  458. }
  459. } // Move image
  460. swiper.$wrapperEl.on(swiper.touchEvents.move, `.${swiper.params.zoom.containerClass}`, onTouchMove, activeListenerWithCapture);
  461. }
  462. function disable() {
  463. const zoom = swiper.zoom;
  464. if (!zoom.enabled) return;
  465. const support = swiper.support;
  466. zoom.enabled = false;
  467. const {
  468. passiveListener,
  469. activeListenerWithCapture
  470. } = getListeners();
  471. const slideSelector = getSlideSelector(); // Scale image
  472. if (support.gestures) {
  473. swiper.$wrapperEl.off(swiper.touchEvents.start, enableGestures, passiveListener);
  474. swiper.$wrapperEl.off(swiper.touchEvents.end, disableGestures, passiveListener);
  475. } else if (swiper.touchEvents.start === 'touchstart') {
  476. swiper.$wrapperEl.off(swiper.touchEvents.start, slideSelector, onGestureStart, passiveListener);
  477. swiper.$wrapperEl.off(swiper.touchEvents.move, slideSelector, onGestureChange, activeListenerWithCapture);
  478. swiper.$wrapperEl.off(swiper.touchEvents.end, slideSelector, onGestureEnd, passiveListener);
  479. if (swiper.touchEvents.cancel) {
  480. swiper.$wrapperEl.off(swiper.touchEvents.cancel, slideSelector, onGestureEnd, passiveListener);
  481. }
  482. } // Move image
  483. swiper.$wrapperEl.off(swiper.touchEvents.move, `.${swiper.params.zoom.containerClass}`, onTouchMove, activeListenerWithCapture);
  484. }
  485. on('init', () => {
  486. if (swiper.params.zoom.enabled) {
  487. enable();
  488. }
  489. });
  490. on('destroy', () => {
  491. disable();
  492. });
  493. on('touchStart', (_s, e) => {
  494. if (!swiper.zoom.enabled) return;
  495. onTouchStart(e);
  496. });
  497. on('touchEnd', (_s, e) => {
  498. if (!swiper.zoom.enabled) return;
  499. onTouchEnd(e);
  500. });
  501. on('doubleTap', (_s, e) => {
  502. if (!swiper.animating && swiper.params.zoom.enabled && swiper.zoom.enabled && swiper.params.zoom.toggle) {
  503. zoomToggle(e);
  504. }
  505. });
  506. on('transitionEnd', () => {
  507. if (swiper.zoom.enabled && swiper.params.zoom.enabled) {
  508. onTransitionEnd();
  509. }
  510. });
  511. on('slideChange', () => {
  512. if (swiper.zoom.enabled && swiper.params.zoom.enabled && swiper.params.cssMode) {
  513. onTransitionEnd();
  514. }
  515. });
  516. Object.assign(swiper.zoom, {
  517. enable,
  518. disable,
  519. in: zoomIn,
  520. out: zoomOut,
  521. toggle: zoomToggle
  522. });
  523. }