Wedding Invitation
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

app.js 7.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. import './bootstrap';
  2. //import 'resources/js/app.js';
  3. import '@fortawesome/fontawesome-free/css/all.min.css';
  4. document.addEventListener('DOMContentLoaded', function () {
  5. imageLoading()
  6. scrollOpenCover();
  7. reset() // reset everrything to ensure smooth
  8. sessionStorage.setItem("initial-load", "true"); // will be used by click event
  9. });
  10. document.addEventListener('click', function () {
  11. let initLoad = sessionStorage.getItem("initial-load")
  12. // parts is intro cover
  13. let parts = document.getElementsByClassName("part");
  14. for (let part of parts) {
  15. part.classList.add("shadow-lg")
  16. }
  17. let body = document.querySelector("body");
  18. body.classList.remove("no-scroll");
  19. // the intro - only done once and
  20. if (initLoad == "true") {
  21. playMusic();
  22. sessionStorage.removeItem("initial-load")
  23. // delay timer to have that umpph feels my G
  24. setTimeout(() => {
  25. // smooth scroll only happen for first render
  26. smoothScrollBy(100, 3500);
  27. }, 600)
  28. }
  29. setTimeout(() => {
  30. eventCountdown();
  31. let petalOverlay = document.getElementById("petalOverlay");
  32. petalOverlay.classList.remove("hidden");
  33. }, 5000)
  34. });
  35. function smoothScrollBy(distance, duration) {
  36. const start = window.pageYOffset;
  37. const startTime = performance.now();
  38. function scroll() {
  39. const now = performance.now();
  40. const time = Math.min(1, (now - startTime) / duration);
  41. const timeFunction = time * (2 - time); // Ease out effect
  42. window.scrollTo(0, start + timeFunction * distance);
  43. if (time < 1) {
  44. requestAnimationFrame(scroll);
  45. }
  46. }
  47. requestAnimationFrame(scroll);
  48. }
  49. // to ensure all images is loaded before starting animation and gimmick
  50. function imageLoading() {
  51. const images = document.querySelectorAll("img");
  52. let loadedCount = 0;
  53. const totalImages = images.length;
  54. images.forEach(image => {
  55. if (image.complete) {
  56. loadedCount++;
  57. } else {
  58. image.addEventListener("load", () => {
  59. loadedCount++;
  60. checkAllImagesLoaded();
  61. });
  62. image.addEventListener("error", () => {
  63. loadedCount++;
  64. checkAllImagesLoaded();
  65. });
  66. }
  67. });
  68. function checkAllImagesLoaded() {
  69. if (loadedCount === totalImages) {
  70. let loading = document.getElementById("loading");
  71. loading.remove();
  72. // parts is intro cover
  73. let parts = document.getElementsByClassName("part");
  74. for (let part of parts) {
  75. part.classList.remove("hidden")
  76. }
  77. }
  78. }
  79. //somehow the server work so fast, script doesn't have much time to set the load eventlistener
  80. //thus we check here, to ensure checkAllImagesLoaded run
  81. checkAllImagesLoaded();
  82. }
  83. // enable open close cover
  84. function scrollOpenCover() {
  85. var partLeftPos = 0;
  86. var partRightPos = 0;
  87. function updatePositions() {
  88. var distance = $(window).scrollTop() * 2;
  89. var left = partLeftPos - distance;
  90. var right = partRightPos - distance;
  91. $('.left').css('left', left + "px");
  92. $('.right').css('right', right + "px");
  93. //Calculate boundaries
  94. var leftPartRightEdge = $('.left').offset().left + $('.left').outerWidth();
  95. //Check if both parts are completely off-screen
  96. var isLeftOffScreen = leftPartRightEdge <= 0;
  97. //Toggle visibility and z-index
  98. if (isLeftOffScreen && left < 0) {
  99. $('.parent').removeClass('z-30');
  100. } else {
  101. $('.parent').addClass('z-30');
  102. }
  103. }
  104. //Initial positions update
  105. updatePositions();
  106. //Listen to scroll events using requestAnimationFrame for smooth animation
  107. var ticking = false;
  108. $(window).scroll(function () {
  109. if (!ticking) {
  110. window.requestAnimationFrame(function () {
  111. updatePositions();
  112. ticking = false;
  113. });
  114. }
  115. ticking = true;
  116. });
  117. }
  118. function reset() {
  119. // reset to top
  120. let body = document.querySelector("body");
  121. body.classList.remove("no-scroll");
  122. window.scrollTo(0, 0);
  123. setTimeout(() => {
  124. body.classList.add("no-scroll");
  125. }, 100)
  126. }
  127. function playMusic() {
  128. var audioElement = document.getElementById('player');
  129. var hasPlayed = false;
  130. if (!hasPlayed) {
  131. console.log('play')
  132. var playPromise = audioElement.play();
  133. if (playPromise !== undefined) {
  134. playPromise.then(function () {
  135. // Automatic playback started!
  136. hasPlayed = true; // Prevent further attempts to play
  137. }).catch(function (error) {
  138. // Automatic playback failed.
  139. console.log('Autoplay failed: ' + error);
  140. });
  141. }
  142. }
  143. }
  144. function eventCountdown() {
  145. //Countdown date (adjust this date to your desired countdown target)
  146. const countdownDate = new Date('2024-08-17T11:00:00').getTime();
  147. //Update the countdown every second
  148. const countdownElement = document.getElementById('countdown');
  149. const countdownTimer = setInterval(() => {
  150. //Get the current date and time
  151. const now = new Date().getTime();
  152. //Calculate the time remaining
  153. const distance = countdownDate - now;
  154. //Calculate days, hours, minutes, and seconds
  155. const days = Math.floor(distance / (1000 * 60 * 60 * 24));
  156. const hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
  157. const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
  158. const seconds = Math.floor((distance % (1000 * 60)) / 1000);
  159. //Format the countdown into a string
  160. const countdownHTML = `
  161. <div class="flex flex-col">
  162. <div class="flex gap-8 justify-center">
  163. <div class="font-medium text-gray-500">${days}</div>
  164. <div class="font-medium text-gray-500">:</div>
  165. <div class="font-medium text-gray-500">${hours.toString().padStart(2, '0')}</div>
  166. <div class="font-medium text-gray-500">:</div>
  167. <div class="font-medium text-gray-500">${minutes.toString().padStart(2, '0')}</div>
  168. <div class="font-medium text-gray-500">:</div>
  169. <div class="font-medium text-gray-500">${seconds.toString().padStart(2, '0')}</div>
  170. </div>
  171. <div class="flex gap-14 justify-center">
  172. <div class="font-medium text-gray-600">Hari</div>
  173. <div class="font-medium text-gray-600">Jam</div>
  174. <div class="font-medium text-gray-600">Minit</div>
  175. <div class="font-medium text-gray-600">Saat</div>
  176. </div>
  177. </div>
  178. `;
  179. //Display the countdown in the element
  180. countdownElement.innerHTML = countdownHTML;
  181. //If the countdown is over, clear the timer and display a message
  182. if (distance < 0) {
  183. clearInterval(countdownTimer);
  184. countdownElement.innerHTML = 'Majlis berlangsung';
  185. }
  186. }, 1000); // Update every second (1000 milliseconds)
  187. }