Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 

238 рядки
6.7 KiB

  1. const $ = require('jquery');
  2. import Slider from "../../sections/slider/slider";
  3. class IHKTimeline {
  4. constructor(section) {
  5. section.addClass('initiated');
  6. this.section = section;
  7. this.itemSlider = section.find('.item-slider');
  8. this.yearsWrapper = section.find('.years-wrapper');
  9. this.yearsContainer = section.find('.years .container');
  10. this.years = this.yearsWrapper.find('.year-item');
  11. this.initResize();
  12. this.initDragging();
  13. this.buildSlider();
  14. this.initYearClick();
  15. this.activateItem(0);
  16. this.initSwitch();
  17. // this.initDocking();
  18. }
  19. initDocking() {
  20. this.winPosition = 0;
  21. this.secPosition = $(this.section.parent()).offset().top;
  22. this.scrolling = false;
  23. $(window).on('scroll', () => {
  24. if (this.scrolling) {
  25. return false;
  26. }
  27. const st = $(window).scrollTop();
  28. if (st > this.winPosition && st < this.secPosition - 100) {
  29. this.scrolling = true;
  30. $('html, body').animate({scrollTop: this.secPosition - 100}, 200, () => {
  31. this.scrolling = false;
  32. })
  33. }
  34. this.winPosition = st;
  35. })
  36. }
  37. initSwitch() {
  38. this.switches = this.section.siblings('.timeline-tabs').find('a');
  39. this.switchSlides = [];
  40. this.switches.each((index, tab) => {
  41. const href = tab.href;
  42. const id = href.substr(href.indexOf('#'));
  43. const target = parseInt($(id).attr('data-index'));
  44. this.switchSlides.push(target);
  45. tab.setAttribute('data-index', index);
  46. tab.setAttribute('data-target', target);
  47. })
  48. this.slider.section.on('slide-change', () => {
  49. this.switches.removeClass('active');
  50. const cs = this.slider.currentSlide;
  51. let i = this.switchSlides.length - 1;
  52. while (i >= 0) {
  53. if (cs >= this.switchSlides[i]) {
  54. this.switches.eq(i).addClass('active');
  55. break;
  56. }
  57. i--;
  58. }
  59. })
  60. this.switches.on('click', (e) => {
  61. e.preventDefault();
  62. const target = parseInt(e.currentTarget.getAttribute('data-target'));
  63. this.slider.goTo(target, false);
  64. })
  65. }
  66. initResize() {
  67. this.resizeTimeout = null;
  68. $(window).on('resize', () => {
  69. if (this.resizeTimeout) {
  70. clearTimeout(this.resizeTimeout);
  71. }
  72. this.resizeTimeout = setTimeout(() => {
  73. this.handleResize();
  74. }, 200)
  75. })
  76. this.handleResize();
  77. }
  78. handleResize() {
  79. this.containerWidth = this.yearsContainer.width();
  80. this.wrapperWidth = this.yearsWrapper.get(0).scrollWidth;
  81. this.scrollWidth = this.containerWidth - this.wrapperWidth;
  82. this.yearsWrapper.css({'width': this.wrapperWidth + 'px'});
  83. }
  84. initDragging() {
  85. this.dragOffset = 0;
  86. this.wrapperOffset = 0;
  87. this.yearsWrapper.get(0).onmousedown = (e) => { this.dragStart(e) };
  88. this.yearsWrapper.get(0).addEventListener('touchstart', (e) => {this.dragStart(e)});
  89. this.yearsWrapper.get(0).addEventListener('touchend', (e) => {this.dragEnd(e)});
  90. this.yearsWrapper.get(0).addEventListener('touchmove', (e) => {this.dragMove(e)});
  91. }
  92. dragStart(e) {
  93. this.dragOffset = 0;
  94. this.dragLast = 0;
  95. if (e.type === 'touchstart') {
  96. this.dragOrigin = e.touches[0].clientX;
  97. } else {
  98. this.dragOrigin = e.clientX;
  99. document.onmouseup = (e) => { this.dragEnd(e) };
  100. document.onmousemove = (e) => { this.dragMove(e) };
  101. }
  102. }
  103. dragMove(e) {
  104. if (e.type === 'touchmove') {
  105. this.dragLast = this.dragOffset;
  106. this.dragOffset = this.dragOrigin - e.touches[0].clientX;
  107. } else {
  108. this.dragLast = this.dragOffset;
  109. this.dragOffset = this.dragOrigin - e.clientX;
  110. }
  111. if (Math.abs(this.dragOffset) > 3) {
  112. this.yearsWrapper.addClass('dragging');
  113. }
  114. this.wrapperTarget = this.wrapperOffset - this.dragOffset;
  115. if (this.wrapperTarget > 0) {
  116. this.wrapperTarget = this.wrapperTarget / 4;
  117. } else if (this.wrapperTarget < this.scrollWidth) {
  118. this.wrapperTarget = this.scrollWidth + (this.wrapperTarget - this.scrollWidth) / 4;
  119. }
  120. this.yearsWrapper.css({'transform': 'translateX(' + this.wrapperTarget + 'px)'});
  121. }
  122. dragEnd() {
  123. const velocity = this.dragOffset - this.dragLast;
  124. if (Math.abs(velocity) > 5) {
  125. this.wrapperTarget = this.wrapperTarget - velocity * 10;
  126. }
  127. const bounceBack = this.checkScrollEnd();
  128. this.yearsWrapper.removeClass('dragging');
  129. this.wrapperOffset = this.wrapperTarget;
  130. if (bounceBack || Math.abs(velocity) > 5) {
  131. this.animateToPosition();
  132. }
  133. document.onmouseup = null;
  134. document.onmousemove = null;
  135. }
  136. animateToPosition() {
  137. this.yearsWrapper.addClass('animate');
  138. requestAnimationFrame(() => {
  139. this.yearsWrapper.css({'transform': 'translateX(' + this.wrapperTarget + 'px)'});
  140. setTimeout(() => {
  141. this.yearsWrapper.removeClass('animate');
  142. }, 300);
  143. })
  144. }
  145. buildSlider() {
  146. const slides = this.itemSlider.addClass('slider').appendTo(this.itemSlider);
  147. this.years.find('.items > li').each((i, li) => {
  148. const listItem = $(li);
  149. listItem.attr('data-index', i).find('.slide').appendTo(slides);
  150. listItem.on('click', () => {
  151. this.slider.goTo(i, true);
  152. this.activateItem(i);
  153. })
  154. })
  155. this.slider = new Slider(slides);
  156. this.slider.section.on('slide-change', () => {
  157. this.activateItem(this.slider.currentSlide);
  158. })
  159. this.slides = this.slider.section.find('.slide');
  160. }
  161. initYearClick() {
  162. this.years.children('.year').on('click', (e) => {
  163. $(e.currentTarget).next('.items').children('li').first().trigger('click');
  164. })
  165. }
  166. activateItem(index) {
  167. this.years.removeClass('current').find('li.active').removeClass('active');
  168. const yearItem = this.years.find('li[data-index="' + index + '"]').addClass('active').closest('.year-item').addClass('current');
  169. const ww = $(window).width();
  170. const iw = yearItem.outerWidth() * 1.5;
  171. if (yearItem.offset().left + iw > ww || yearItem.offset().left < 50) {
  172. this.wrapperOffset = this.wrapperTarget = yearItem.position().left * -1;
  173. this.checkScrollEnd();
  174. this.animateToPosition();
  175. }
  176. if (this.slides.eq(index).hasClass('has-image')) {
  177. this.slider.section.addClass('hide-circle');
  178. } else {
  179. this.slider.section.removeClass('hide-circle');
  180. }
  181. }
  182. checkScrollEnd() {
  183. if (this.wrapperTarget > 0) {
  184. this.wrapperTarget = 0;
  185. return true;
  186. } else if (this.wrapperTarget < this.scrollWidth) {
  187. this.wrapperTarget = this.scrollWidth;
  188. return true;
  189. }
  190. return false;
  191. }
  192. }
  193. export default IHKTimeline;
  194. $('body').on('ihk-init dynamic-component-loaded gfi-dynamic-init', function () {
  195. $('.timeline:not(.initiated)').each((i, el) => {
  196. new IHKTimeline($(el));
  197. })
  198. })