Просмотр файла wu-static/js/lightgallery/js/lg-zoom.js

Размер файла: 15.93Kb
  1. /*! lg-zoom - v1.0.0 - 2016-09-20
  2. * http://sachinchoolur.github.io/lightGallery
  3. * Copyright (c) 2016 Sachin N; Licensed GPLv3 */
  4.  
  5. (function (root, factory) {
  6. if (typeof define === 'function' && define.amd) {
  7. // AMD. Register as an anonymous module unless amdModuleId is set
  8. define([], function () {
  9. return (factory());
  10. });
  11. } else if (typeof exports === 'object') {
  12. // Node. Does not work with strict CommonJS, but
  13. // only CommonJS-like environments that support module.exports,
  14. // like Node.
  15. module.exports = factory();
  16. } else {
  17. factory();
  18. }
  19. }(this, function () {
  20.  
  21. (function($, window, document, undefined) {
  22.  
  23. 'use strict';
  24.  
  25. var defaults = {
  26. scale: 1,
  27. zoom: true,
  28. actualSize: true,
  29. enableZoomAfter: 300
  30. };
  31.  
  32. var Zoom = function(element) {
  33.  
  34. this.core = $(element).data('lightGallery');
  35.  
  36. this.core.s = $.extend({}, defaults, this.core.s);
  37.  
  38. if (this.core.s.zoom && this.core.doCss()) {
  39. this.init();
  40.  
  41. // Store the zoomable timeout value just to clear it while closing
  42. this.zoomabletimeout = false;
  43.  
  44. // Set the initial value center
  45. this.pageX = $(window).width() / 2;
  46. this.pageY = ($(window).height() / 2) + $(window).scrollTop();
  47. }
  48.  
  49. return this;
  50. };
  51.  
  52. Zoom.prototype.init = function() {
  53.  
  54. var _this = this;
  55. var zoomIcons = '<span id="lg-zoom-in" class="lg-icon"></span><span id="lg-zoom-out" class="lg-icon"></span>';
  56.  
  57. if (_this.core.s.actualSize) {
  58. zoomIcons += '<span id="lg-actual-size" class="lg-icon"></span>';
  59. }
  60.  
  61. this.core.$outer.find('.lg-toolbar').append(zoomIcons);
  62.  
  63. // Add zoomable class
  64. _this.core.$el.on('onSlideItemLoad.lg.tm.zoom', function(event, index, delay) {
  65.  
  66. // delay will be 0 except first time
  67. var _speed = _this.core.s.enableZoomAfter + delay;
  68.  
  69. // set _speed value 0 if gallery opened from direct url and if it is first slide
  70. if ($('body').hasClass('lg-from-hash') && delay) {
  71.  
  72. // will execute only once
  73. _speed = 0;
  74. } else {
  75.  
  76. // Remove lg-from-hash to enable starting animation.
  77. $('body').removeClass('lg-from-hash');
  78. }
  79.  
  80. _this.zoomabletimeout = setTimeout(function() {
  81. _this.core.$slide.eq(index).addClass('lg-zoomable');
  82. }, _speed + 30);
  83. });
  84.  
  85. var scale = 1;
  86. /**
  87. * @desc Image zoom
  88. * Translate the wrap and scale the image to get better user experience
  89. *
  90. * @param {String} scaleVal - Zoom decrement/increment value
  91. */
  92. var zoom = function(scaleVal) {
  93.  
  94. var $image = _this.core.$outer.find('.lg-current .lg-image');
  95. var _x;
  96. var _y;
  97.  
  98. // Find offset manually to avoid issue after zoom
  99. var offsetX = ($(window).width() - $image.width()) / 2;
  100. var offsetY = (($(window).height() - $image.height()) / 2) + $(window).scrollTop();
  101.  
  102. _x = _this.pageX - offsetX;
  103. _y = _this.pageY - offsetY;
  104.  
  105. var x = (scaleVal - 1) * (_x);
  106. var y = (scaleVal - 1) * (_y);
  107.  
  108. $image.css('transform', 'scale3d(' + scaleVal + ', ' + scaleVal + ', 1)').attr('data-scale', scaleVal);
  109.  
  110. $image.parent().css({
  111. left: -x + 'px',
  112. top: -y + 'px'
  113. }).attr('data-x', x).attr('data-y', y);
  114. };
  115.  
  116. var callScale = function() {
  117. if (scale > 1) {
  118. _this.core.$outer.addClass('lg-zoomed');
  119. } else {
  120. _this.resetZoom();
  121. }
  122.  
  123. if (scale < 1) {
  124. scale = 1;
  125. }
  126.  
  127. zoom(scale);
  128. };
  129.  
  130. var actualSize = function(event, $image, index, fromIcon) {
  131. var w = $image.width();
  132. var nw;
  133. if (_this.core.s.dynamic) {
  134. nw = _this.core.s.dynamicEl[index].width || $image[0].naturalWidth || w;
  135. } else {
  136. nw = _this.core.$items.eq(index).attr('data-width') || $image[0].naturalWidth || w;
  137. }
  138.  
  139. var _scale;
  140.  
  141. if (_this.core.$outer.hasClass('lg-zoomed')) {
  142. scale = 1;
  143. } else {
  144. if (nw > w) {
  145. _scale = nw / w;
  146. scale = _scale || 2;
  147. }
  148. }
  149.  
  150. if (fromIcon) {
  151. _this.pageX = $(window).width() / 2;
  152. _this.pageY = ($(window).height() / 2) + $(window).scrollTop();
  153. } else {
  154. _this.pageX = event.pageX || event.originalEvent.targetTouches[0].pageX;
  155. _this.pageY = event.pageY || event.originalEvent.targetTouches[0].pageY;
  156. }
  157.  
  158. callScale();
  159. setTimeout(function() {
  160. _this.core.$outer.removeClass('lg-grabbing').addClass('lg-grab');
  161. }, 10);
  162. };
  163.  
  164. var tapped = false;
  165.  
  166. // event triggered after appending slide content
  167. _this.core.$el.on('onAferAppendSlide.lg.tm.zoom', function(event, index) {
  168.  
  169. // Get the current element
  170. var $image = _this.core.$slide.eq(index).find('.lg-image');
  171.  
  172. $image.on('dblclick', function(event) {
  173. actualSize(event, $image, index);
  174. });
  175.  
  176. $image.on('touchstart', function(event) {
  177. if (!tapped) {
  178. tapped = setTimeout(function() {
  179. tapped = null;
  180. }, 300);
  181. } else {
  182. clearTimeout(tapped);
  183. tapped = null;
  184. actualSize(event, $image, index);
  185. }
  186.  
  187. event.preventDefault();
  188. });
  189.  
  190. });
  191.  
  192. // Update zoom on resize and orientationchange
  193. $(window).on('resize.lg.zoom scroll.lg.zoom orientationchange.lg.zoom', function() {
  194. _this.pageX = $(window).width() / 2;
  195. _this.pageY = ($(window).height() / 2) + $(window).scrollTop();
  196. zoom(scale);
  197. });
  198.  
  199. $('#lg-zoom-out').on('click.lg', function() {
  200. if (_this.core.$outer.find('.lg-current .lg-image').length) {
  201. scale -= _this.core.s.scale;
  202. callScale();
  203. }
  204. });
  205.  
  206. $('#lg-zoom-in').on('click.lg', function() {
  207. if (_this.core.$outer.find('.lg-current .lg-image').length) {
  208. scale += _this.core.s.scale;
  209. callScale();
  210. }
  211. });
  212.  
  213. $('#lg-actual-size').on('click.lg', function(event) {
  214. actualSize(event, _this.core.$slide.eq(_this.core.index).find('.lg-image'), _this.core.index, true);
  215. });
  216.  
  217. // Reset zoom on slide change
  218. _this.core.$el.on('onBeforeSlide.lg.tm', function() {
  219. scale = 1;
  220. _this.resetZoom();
  221. });
  222.  
  223. // Drag option after zoom
  224. if (!_this.core.isTouch) {
  225. _this.zoomDrag();
  226. }
  227.  
  228. if (_this.core.isTouch) {
  229. _this.zoomSwipe();
  230. }
  231.  
  232. };
  233.  
  234. // Reset zoom effect
  235. Zoom.prototype.resetZoom = function() {
  236. this.core.$outer.removeClass('lg-zoomed');
  237. this.core.$slide.find('.lg-img-wrap').removeAttr('style data-x data-y');
  238. this.core.$slide.find('.lg-image').removeAttr('style data-scale');
  239.  
  240. // Reset pagx pagy values to center
  241. this.pageX = $(window).width() / 2;
  242. this.pageY = ($(window).height() / 2) + $(window).scrollTop();
  243. };
  244.  
  245. Zoom.prototype.zoomSwipe = function() {
  246. var _this = this;
  247. var startCoords = {};
  248. var endCoords = {};
  249. var isMoved = false;
  250.  
  251. // Allow x direction drag
  252. var allowX = false;
  253.  
  254. // Allow Y direction drag
  255. var allowY = false;
  256.  
  257. _this.core.$slide.on('touchstart.lg', function(e) {
  258.  
  259. if (_this.core.$outer.hasClass('lg-zoomed')) {
  260. var $image = _this.core.$slide.eq(_this.core.index).find('.lg-object');
  261.  
  262. allowY = $image.outerHeight() * $image.attr('data-scale') > _this.core.$outer.find('.lg').height();
  263. allowX = $image.outerWidth() * $image.attr('data-scale') > _this.core.$outer.find('.lg').width();
  264. if ((allowX || allowY)) {
  265. e.preventDefault();
  266. startCoords = {
  267. x: e.originalEvent.targetTouches[0].pageX,
  268. y: e.originalEvent.targetTouches[0].pageY
  269. };
  270. }
  271. }
  272.  
  273. });
  274.  
  275. _this.core.$slide.on('touchmove.lg', function(e) {
  276.  
  277. if (_this.core.$outer.hasClass('lg-zoomed')) {
  278.  
  279. var _$el = _this.core.$slide.eq(_this.core.index).find('.lg-img-wrap');
  280. var distanceX;
  281. var distanceY;
  282.  
  283. e.preventDefault();
  284. isMoved = true;
  285.  
  286. endCoords = {
  287. x: e.originalEvent.targetTouches[0].pageX,
  288. y: e.originalEvent.targetTouches[0].pageY
  289. };
  290.  
  291. // reset opacity and transition duration
  292. _this.core.$outer.addClass('lg-zoom-dragging');
  293.  
  294. if (allowY) {
  295. distanceY = (-Math.abs(_$el.attr('data-y'))) + (endCoords.y - startCoords.y);
  296. } else {
  297. distanceY = -Math.abs(_$el.attr('data-y'));
  298. }
  299.  
  300. if (allowX) {
  301. distanceX = (-Math.abs(_$el.attr('data-x'))) + (endCoords.x - startCoords.x);
  302. } else {
  303. distanceX = -Math.abs(_$el.attr('data-x'));
  304. }
  305.  
  306. if ((Math.abs(endCoords.x - startCoords.x) > 15) || (Math.abs(endCoords.y - startCoords.y) > 15)) {
  307. _$el.css({
  308. left: distanceX + 'px',
  309. top: distanceY + 'px'
  310. });
  311. }
  312.  
  313. }
  314.  
  315. });
  316.  
  317. _this.core.$slide.on('touchend.lg', function() {
  318. if (_this.core.$outer.hasClass('lg-zoomed')) {
  319. if (isMoved) {
  320. isMoved = false;
  321. _this.core.$outer.removeClass('lg-zoom-dragging');
  322. _this.touchendZoom(startCoords, endCoords, allowX, allowY);
  323.  
  324. }
  325. }
  326. });
  327.  
  328. };
  329.  
  330. Zoom.prototype.zoomDrag = function() {
  331.  
  332. var _this = this;
  333. var startCoords = {};
  334. var endCoords = {};
  335. var isDraging = false;
  336. var isMoved = false;
  337.  
  338. // Allow x direction drag
  339. var allowX = false;
  340.  
  341. // Allow Y direction drag
  342. var allowY = false;
  343.  
  344. _this.core.$slide.on('mousedown.lg.zoom', function(e) {
  345.  
  346. // execute only on .lg-object
  347. var $image = _this.core.$slide.eq(_this.core.index).find('.lg-object');
  348.  
  349. allowY = $image.outerHeight() * $image.attr('data-scale') > _this.core.$outer.find('.lg').height();
  350. allowX = $image.outerWidth() * $image.attr('data-scale') > _this.core.$outer.find('.lg').width();
  351.  
  352. if (_this.core.$outer.hasClass('lg-zoomed')) {
  353. if ($(e.target).hasClass('lg-object') && (allowX || allowY)) {
  354. e.preventDefault();
  355. startCoords = {
  356. x: e.pageX,
  357. y: e.pageY
  358. };
  359.  
  360. isDraging = true;
  361.  
  362. // ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
  363. _this.core.$outer.scrollLeft += 1;
  364. _this.core.$outer.scrollLeft -= 1;
  365.  
  366. _this.core.$outer.removeClass('lg-grab').addClass('lg-grabbing');
  367. }
  368. }
  369. });
  370.  
  371. $(window).on('mousemove.lg.zoom', function(e) {
  372. if (isDraging) {
  373. var _$el = _this.core.$slide.eq(_this.core.index).find('.lg-img-wrap');
  374. var distanceX;
  375. var distanceY;
  376.  
  377. isMoved = true;
  378. endCoords = {
  379. x: e.pageX,
  380. y: e.pageY
  381. };
  382.  
  383. // reset opacity and transition duration
  384. _this.core.$outer.addClass('lg-zoom-dragging');
  385.  
  386. if (allowY) {
  387. distanceY = (-Math.abs(_$el.attr('data-y'))) + (endCoords.y - startCoords.y);
  388. } else {
  389. distanceY = -Math.abs(_$el.attr('data-y'));
  390. }
  391.  
  392. if (allowX) {
  393. distanceX = (-Math.abs(_$el.attr('data-x'))) + (endCoords.x - startCoords.x);
  394. } else {
  395. distanceX = -Math.abs(_$el.attr('data-x'));
  396. }
  397.  
  398. _$el.css({
  399. left: distanceX + 'px',
  400. top: distanceY + 'px'
  401. });
  402. }
  403. });
  404.  
  405. $(window).on('mouseup.lg.zoom', function(e) {
  406.  
  407. if (isDraging) {
  408. isDraging = false;
  409. _this.core.$outer.removeClass('lg-zoom-dragging');
  410.  
  411. // Fix for chrome mouse move on click
  412. if (isMoved && ((startCoords.x !== endCoords.x) || (startCoords.y !== endCoords.y))) {
  413. endCoords = {
  414. x: e.pageX,
  415. y: e.pageY
  416. };
  417. _this.touchendZoom(startCoords, endCoords, allowX, allowY);
  418.  
  419. }
  420.  
  421. isMoved = false;
  422. }
  423.  
  424. _this.core.$outer.removeClass('lg-grabbing').addClass('lg-grab');
  425.  
  426. });
  427. };
  428.  
  429. Zoom.prototype.touchendZoom = function(startCoords, endCoords, allowX, allowY) {
  430.  
  431. var _this = this;
  432. var _$el = _this.core.$slide.eq(_this.core.index).find('.lg-img-wrap');
  433. var $image = _this.core.$slide.eq(_this.core.index).find('.lg-object');
  434. var distanceX = (-Math.abs(_$el.attr('data-x'))) + (endCoords.x - startCoords.x);
  435. var distanceY = (-Math.abs(_$el.attr('data-y'))) + (endCoords.y - startCoords.y);
  436. var minY = (_this.core.$outer.find('.lg').height() - $image.outerHeight()) / 2;
  437. var maxY = Math.abs(($image.outerHeight() * Math.abs($image.attr('data-scale'))) - _this.core.$outer.find('.lg').height() + minY);
  438. var minX = (_this.core.$outer.find('.lg').width() - $image.outerWidth()) / 2;
  439. var maxX = Math.abs(($image.outerWidth() * Math.abs($image.attr('data-scale'))) - _this.core.$outer.find('.lg').width() + minX);
  440.  
  441. if ((Math.abs(endCoords.x - startCoords.x) > 15) || (Math.abs(endCoords.y - startCoords.y) > 15)) {
  442. if (allowY) {
  443. if (distanceY <= -maxY) {
  444. distanceY = -maxY;
  445. } else if (distanceY >= -minY) {
  446. distanceY = -minY;
  447. }
  448. }
  449.  
  450. if (allowX) {
  451. if (distanceX <= -maxX) {
  452. distanceX = -maxX;
  453. } else if (distanceX >= -minX) {
  454. distanceX = -minX;
  455. }
  456. }
  457.  
  458. if (allowY) {
  459. _$el.attr('data-y', Math.abs(distanceY));
  460. } else {
  461. distanceY = -Math.abs(_$el.attr('data-y'));
  462. }
  463.  
  464. if (allowX) {
  465. _$el.attr('data-x', Math.abs(distanceX));
  466. } else {
  467. distanceX = -Math.abs(_$el.attr('data-x'));
  468. }
  469.  
  470. _$el.css({
  471. left: distanceX + 'px',
  472. top: distanceY + 'px'
  473. });
  474.  
  475. }
  476. };
  477.  
  478. Zoom.prototype.destroy = function() {
  479.  
  480. var _this = this;
  481.  
  482. // Unbind all events added by lightGallery zoom plugin
  483. _this.core.$el.off('.lg.zoom');
  484. $(window).off('.lg.zoom');
  485. _this.core.$slide.off('.lg.zoom');
  486. _this.core.$el.off('.lg.tm.zoom');
  487. _this.resetZoom();
  488. clearTimeout(_this.zoomabletimeout);
  489. _this.zoomabletimeout = false;
  490. };
  491.  
  492. $.fn.lightGallery.modules.zoom = Zoom;
  493.  
  494. })(jQuery, window, document);
  495.  
  496.  
  497. }));