studio.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. // Studio page — vanilla fade-carousel + tab sync + per-slide choreography.
  2. // Replaces Bootstrap Carousel/Tab, jQuery, and backstretch. Keeps DrawFillSVG
  3. // (window.DrawFillSVG, self-exposed from the v4-script bundle).
  4. // --- shared chrome: navbar hide/show on scroll (ported from jQuery dw_hidenav) ---
  5. (function () {
  6. const navbar = document.querySelector('.navbar');
  7. if (!navbar) return;
  8. const title = document.querySelector('.site-title a');
  9. const headerHeight = navbar.offsetHeight;
  10. let previousTop = 0;
  11. window.addEventListener('scroll', function () {
  12. const currentTop = window.scrollY;
  13. if (currentTop < previousTop) {
  14. if (currentTop > 0 && navbar.classList.contains('fixed')) {
  15. navbar.classList.add('visible');
  16. if (title) title.classList.remove('light');
  17. } else {
  18. navbar.classList.remove('visible', 'fixed');
  19. if (title) title.classList.add('light');
  20. }
  21. } else {
  22. navbar.classList.remove('visible');
  23. if (currentTop > headerHeight && !navbar.classList.contains('fixed')) {
  24. navbar.classList.add('fixed');
  25. }
  26. }
  27. previousTop = currentTop;
  28. }, { passive: true });
  29. })();
  30. document.querySelectorAll('.nav-toggle').forEach(function (el) {
  31. el.addEventListener('click', function (e) {
  32. e.preventDefault();
  33. el.classList.toggle('active');
  34. });
  35. });
  36. // --- studio fade-carousel ---
  37. (function () {
  38. const stage = document.getElementById('studio-caro');
  39. const caro = document.getElementById('caro');
  40. if (!stage || !caro) return;
  41. const slides = Array.from(caro.querySelectorAll('.dw-fade-slide'));
  42. const tabs = Array.from(document.querySelectorAll('.dw-studio-tab'));
  43. const panes = Array.from(document.querySelectorAll('#studio-tab .tab-pane'));
  44. const bg = stage.querySelector('.dw-studio-bg');
  45. const video = stage.querySelector('.dw-studio-video'); // camera → Media slide
  46. const tv = stage.querySelector('.dw-studio-tv'); // grayscale → fact intro
  47. const title = document.querySelector('.site-title a');
  48. const GRADS = ['caro-grad', 'caro-grad2', 'caro-grad3', 'caro-grad5'];
  49. // per slide: gradient class · background image · show video · navbar-title light
  50. // Slides 0-2 are the fact intro (from About); 3-8 are the tabbed sections.
  51. const CONFIG = [
  52. { grad: 'caro-grad5', img: null, video: false, tv: true, light: true }, // 0 fact: web sites
  53. { grad: 'caro-grad5', img: null, video: false, tv: true, light: true }, // 1 fact: stars
  54. { grad: 'caro-grad5', img: null, video: false, tv: true, light: true }, // 2 fact: brain
  55. { grad: 'caro-grad5', img: stage.dataset.bg0 || null, video: false, light: true }, // 3 Studio
  56. { grad: 'caro-grad', img: null, video: false, light: true }, // 4 Web
  57. { grad: 'caro-grad2', img: null, video: false, light: true }, // 5 UX
  58. { grad: 'caro-grad3', img: null, video: false, light: false }, // 6 Graphic
  59. { grad: 'caro-grad5', img: null, video: true, light: true }, // 7 Media
  60. { grad: 'caro-grad5', img: stage.dataset.bg5 || null, video: false, light: true }, // 8 Art
  61. ];
  62. const INTERVAL = 5000;
  63. let index = 0;
  64. let timer = null;
  65. function drawSVGs(slide) {
  66. if (!window.DrawFillSVG) return;
  67. slide.querySelectorAll('svg[id]').forEach(function (svg) {
  68. try {
  69. new window.DrawFillSVG({ elementId: svg.id }).replay();
  70. } catch (e) {
  71. /* svg not animatable — skip */
  72. }
  73. });
  74. }
  75. function activate(i) {
  76. i = (i + slides.length) % slides.length;
  77. index = i;
  78. const cfg = CONFIG[i];
  79. slides.forEach((s, n) => {
  80. const on = n === i;
  81. s.classList.toggle('active', on);
  82. // reveal the active slide's hidden content (.animac.hide-svg, #brain.hide-svg …)
  83. if (on) s.querySelectorAll('.hide-svg').forEach((el) => el.classList.remove('hide-svg'));
  84. });
  85. // activate the tab (+ its panel) that targets this slide, if any.
  86. // The fact intro slides (0-2) have no tab → leave the panels as they were.
  87. const tabIndex = tabs.findIndex((t) => parseInt(t.dataset.slide, 10) === i);
  88. if (tabIndex >= 0) {
  89. tabs.forEach((t, n) => t.classList.toggle('active', n === tabIndex));
  90. panes.forEach((p, n) => p.classList.toggle('active', n === tabIndex));
  91. }
  92. GRADS.forEach((g) => stage.classList.remove(g));
  93. stage.classList.add(cfg.grad);
  94. if (bg) bg.style.backgroundImage = cfg.img ? 'url("' + cfg.img + '")' : '';
  95. if (video) {
  96. if (cfg.video) {
  97. video.style.display = 'block';
  98. video.play().catch(function () {});
  99. } else {
  100. video.pause();
  101. video.style.display = 'none';
  102. }
  103. }
  104. if (tv) {
  105. if (cfg.tv) {
  106. tv.style.display = 'block';
  107. tv.play().catch(function () {});
  108. } else {
  109. tv.pause();
  110. tv.style.display = 'none';
  111. }
  112. }
  113. if (title) title.classList.toggle('light', cfg.light);
  114. drawSVGs(slides[i]);
  115. }
  116. function next() { activate(index + 1); }
  117. function start() { stop(); timer = window.setInterval(next, INTERVAL); }
  118. function stop() { if (timer) { window.clearInterval(timer); timer = null; } }
  119. tabs.forEach(function (t) {
  120. t.addEventListener('click', function (e) {
  121. e.preventDefault();
  122. activate(parseInt(t.dataset.slide, 10) || 0);
  123. start(); // restart the autoplay clock after manual navigation
  124. });
  125. });
  126. // pause autoplay while the pointer is over the hero
  127. stage.addEventListener('mouseenter', stop);
  128. stage.addEventListener('mouseleave', start);
  129. activate(0);
  130. start();
  131. })();