1document.body.classList.add('scroll-locked'); 2 3document.addEventListener('DOMContentLoaded', () => { 4 5 let isMobile = false; 6 let topOffset = 0; 7 8 const introTimelineAnimDuration = 1000; 9 const introTimelineZeroOffset = '-=' + introTimelineAnimDuration; 10 11 const handleResize = () => { 12 isMobile = window.innerWidth < 834; 13 topOffset = 70; 14 } 15 16 handleResize(); 17 window.addEventListener("resize", handleResize()); 18 19 const handleIntroTimeline = () => { 20 const timelineIntro = anime.timeline({ 21 easing: 'easeInOutQuad', 22 duration: introTimelineAnimDuration, 23 autoplay: false 24 }); 25 26 // white bar 27 timelineIntro.add ({ 28 targets: ['.sn_block_cover_bottom_inner_white-bar', '.sn_block_cover_top_inner_white-bar'], 29 translateX: '100%' 30 }) 31 32 // open 33 timelineIntro.add ({ 34 targets: '.sn_block_cover_bottom', 35 translateY: '100%' 36 }).add({ 37 targets: '.sn_block_cover_top', 38 translateY: '-100%' 39 }, introTimelineZeroOffset) 40 41 // ticket come in 42 timelineIntro.add ({
43 targets: '.sn_block_ticket_wr .sn_block_ticket', 44 translateX: ['-90vw', '0vw'], 45 }).add ({ 46 targets: '.sn_block_ticket_countdown-banner', 47 translateX: ['90vw', '0vw'], 48 rotate: 4 49 }, introTimelineZeroOffset) 50 51 // play 52 timelineIntro.play(); 53 window.scroll(0,0); 54 document.body.classList.add('scroll-locked'); 55 } 56 57 handleIntroTimeline(); 58 59 // #endregion 60 61 // #region TICKET - TEXT/VIDEO 62 63 const ticketTimelineAnimDuration = 1000; 64 const ticketTimelineZeroOffset = '-=' + ticketTimelineAnimDuration; 65 66 const handleTicketTimeline = (animateSun = true) => { 67 68 document.querySelector('.sn_block.sn_block_ticket').style.pointerEvents = 'none'; 69 70 const timelineTicket = anime.timeline({ 71 easing: 'easeInOutQuad', 72 duration: ticketTimelineAnimDuration, 73 autoplay: false 74 }); 75 76 // ticket come in 77 if(!isMobile) { 78 timelineTicket.add ({
79 targets: '.sn_block_ticket_wr .sn_block_ticket', 80 rotate: -40, 81 translateY: '200vh' 82 }).add({ 83 targets: '.ticket_right', 84 rotate: 120, 85 }, ticketTimelineZeroOffset).add({ 86 targets: '.sn_block_ticket_countdown-banner.hide-mobile', 87 rotate: 40, 88 translateY: '200vh' 89 }, ticketTimelineZeroOffset).add({ 90 targets: '.sn_block_ticket_countdown-banner.hide-desktop', 91 rotate: 40, 92 translateY: '200vh' 93 }, ticketTimelineZeroOffset) 94 } 95 else 96 { 97 timelineTicket.add({ 98 targets: '.sn_block_ticket_wr .sn_block_ticket .ticket_right', 99 rotate: -22, 100 duration: 200 101 }).add ({ 102 targets: '.sn_block_ticket_wr .sn_block_ticket', 103 rotate: -40, 104 translateY: '200vh' 105 }, '+=200').add({ 106 targets: '.ticket_right', 107 rotate: 120, 108 }, ticketTimelineZeroOffset).add({ 109 targets: '.sn_block_ticket_countdown-banner.hide-mobile', 110 rotate: 40, 111 translateY: '200vh' 112 }, ticketTimelineZeroOffset).add({ 113 targets: '.sn_block_ticket_countdown-banner.hide-desktop', 114 rotate: 40, 115 translateY: '200vh' 116 }, ticketTimelineZeroOffset) 117 } 118 119 // ferris wheel 120 timelineTicket.add({ 121 targets: '.sn_block_ticket .sn_background', 122 scale: 15 123 }) 124 125 // text-video fade in + navbar & download in 126 timelineTicket.add ({ 127 targets: '.sn_block_event_schedule_download_wr', 128 translateY: -78 129 }).add({ 130 targets: '.sn_header', 131 top: 0 132 }, ticketTimelineZeroOffset).add ({ 133 targets: '.progress-bar', 134 translateY: [-200, 0] 135 }, ticketTimelineZeroOffset).add({ 136 targets: '.sn_block.sn_block_ticket', 137 opacity: 0 138 }, ticketTimelineZeroOffset) 139 140 // text-video video & sun in 141 142 timelineTicket.add ({ 143 targets: '.sn_block_text_video .video-content', 144 scale: [0, 1] 145 }).add({ 146 targets: '.decoration-palm-2-stroke', 147 translateX: isMobile ? '70vw' : '17vw' 148 }, ticketTimelineZeroOffset).add ({ 149 targets: '.decoration-palm-2', 150 translateX: isMobile ? '70vw' : '17vw' 151 }, ticketTimelineZeroOffset).add ({ 152 targets: '.decoration-palm-1', 153 translateX: isMobile ? '-40vw' : '-6vw' 154 }, ticketTimelineZeroOffset) 155 156 if(animateSun) { 157 timelineTicket.add({ 158 targets: '.decoration-sun', 159 scale: [0, 1], 160 }, ticketTimelineZeroOffset) 161 } 162 163 timelineTicket.play(); 164 } 165 const ticketRight = document.querySelector('.ticket_right') 166 const ticketLeft = document.querySelector('.ticket_left_content'); 167 if (ticketRight && ticketLeft) { 168 const handleTicketAnimation = () => { 169 handleTicketTimeline(); 170 window.scrollTo(0,0); 171 172 setTimeout(() => { 173 document.body.classList.remove('scroll-locked'); 174 }, 4000); 175 } 176 ticketRight.addEventListener('click', () => { 177 handleTicketAnimation(); 178 }) 179 ticketLeft.addEventListener('click', () => { 180 handleTicketAnimation(); 181 }) 182 } 183 184 // #endregion 185 186 // #region SOCIAL GALLERY ANIMATIONS 187 188 const sgTimelineAnimDuration = 1000; 189 const sgTimelineZeroOffset = '-=' + sgTimelineAnimDuration; 190 191 const handleSocialGalleryTimeline = (reverse = false) => { 192 const socialGalleryTimeline = anime.timeline({ 193 easing: 'easeInOutQuad', 194 duration: sgTimelineAnimDuration, 195 autoplay: false 196 }); 197 198 socialGalleryTimeline.add ({ 199 targets: ['.swe_post:nth-child(4)', '.swe_post:nth-child(5)'], 200 scale: reverse ? [1, 0] : [0, 1] 201 }).add({ 202 targets: ['.swe_post:nth-child(3)', '.swe_post:nth-child(6)', '.swe_post:nth-child(8)'], 203 scale: reverse ? [1, 0] : [0, 1] 204 }).add({ 205 targets: ['.swe_post:nth-child(1)', '.swe_post:nth-child(2)', '.swe_post:nth-child(7)'], 206 scale: reverse ? [1, 0] : [0, 1] 207 }) 208 209 socialGalleryTimeline.play(); 210 } 211 212 // #endregion 213 214 // #region SCROLL 215 216 const clamp = (value, min, max) => { 217 return Math.max(Math.min(value, max), min); 218 } 219 220 // returns normalized value of element's top between the triggerTop and triggerBottom points 221 const getScrollProgress = (elementTop, triggerTop, triggerBottom) => { 222 return(clamp(elementTop, triggerTop, triggerBottom) - triggerBottom) / (tr
222iggerTop - triggerBottom); 223 } 224 225 // animations 226 const sunAnimation = anime({ 227 targets: '.decoration-sun', 228 scale: isMobile ? [1, 6] : [1, 2 + ((clamp(window.innerWidth, 1280, 2560) - 1280) / 1280) * 2], 229 easing: 'linear' 230 }) 231 232 const livestreamAnimation = anime({ 233 targets: '.live_streaming_container_inner', 234 scale: [0.8, 1], 235 easing: 'linear' 236 }) 237 238 // Apply hardware acceleration to slider track 239 const latestNewsContainer = document.querySelector('.latest_news_slider_container'); 240 const sliderTrack = document.querySelector('.latest_news_slider_container .slider-track'); 241 const newsCards = document.querySelectorAll('.news_card'); 242 243 if (sliderTrack) { 244 sliderTrack.style.willChange = 'transform'; 245 sliderTrack.style.transform = 'translateZ(0)'; 246 } 247 248 // Calculate total slides and currently visible slides 249 const calculateSlidePositions = () => { 250 if (!newsCards.length) return { cardWidth: 0, totalPositions: 0, visibleCards: 0 }; 251 252 const cardWidth = newsCards[0].offsetWidth + parseInt(getComputedStyle(newsCards[0]).marginLeft) * 2; 253 const containerWidth = latestNewsContainer ? latestNewsContainer.offsetWidth : 0; 254 const visibleCards = Math.floor(containerWidth / cardWidth); 255 const totalPositions = Math.max(0, newsCards.length - visibleCards); 256 257 return { 258 cardWidth, 259 totalPositions, 260 visibleCards 261 }; 262 }; 263 264 // Current snap position 265 let currentSnapPosition = 0; 266 267 // Simple snap animation with hardware acceleration 268 const latestNewsAnimation = () => { 269 const { cardWidth, totalPositions } = calculateSlidePositions(); 270 271 // Calculate target position based on scroll progress 272 const latestNews = document.querySelector('.sn_block.sn_block_latest_news'); 273 const latestNewsTop = latestNews ? latestNews.getBoundingClientRect().top : 0; 274 const scrollProgress = getScrollProgress( 275 latestNewsTop, 276 -(latestNews.getBoundingClientRect().height - window.innerHeight), 277 topOffset 278 ); 279 280 // Convert continuous scroll progress to discrete snap positions 281 const targetPosition = Math.min( 282 totalPositions, 283 Math.round(scrollProgress * totalPositions) 284 ); 285 286 // Only update if we're changing positions 287 if (targetPosition !== currentSnapPosition) { 288 currentSnapPosition = targetPosition; 289 290 // Animate to the new position with hardware acceleration 291 anime({ 292 targets: sliderTrack, 293 translateX: -currentSnapPosition * cardWidth, 294 easing: 'easeOutExpo', 295 duration: 500, 296 complete: () => { 297 // Force GPU acceleration and prevent subpixel rendering after animation completes 298 sliderTrack.style.transform = `translateX(${-currentSnapPosition * cardWidth}px) translateZ(0)`; 299 } 300 }); 301 } 302 }; 303 304 anime.set('.news_card:nth-child(even)', { rotate: 4 }); 305 anime.set('.news_card:nth-child(odd)', { rotate: -4 }); 306 307 const latestNewsCardEven = anime ({ 308 targets: '.news_card:nth-child(even)', 309 rotate: [4, -4, 4], 310 easing: 'linear', 311 autoplay: false 312 }) 313 const latestNewsCardOdd = anime({ 314 targets: '.news_card:nth-child(odd)', 315 rotate: [-4, 4, -4], 316 easing: 'linear', 317 autoplay: false 318 }) 319 320 // execute animations 321 const handleScrollAnimations = () => { 322 // text-video sun 323 const textVideoBlock = document.querySelector('.sn_block.sn_block_text_video'); 324 const textVideoTop = textVideoBlock ? textVideoBlock.getBoundingClientRect().top : 0; 325 const sunAnimationPercent = getScrollProgress(textVideoTop, -window.innerHeight * 0.75, topOffset); 326 327 sunAnimation.seek(sunAnimationPercent * sunAnimation.duration) 328 329 // livestream 330 const livestream = document.querySelector('.live_streaming_container_inner'); 331 const livestreamTop = livestream ? livestream.getBoundingClientRect().top : 0; 332 const livestreamAnimationProgress = getScrollProgress(livestreamTop, 90, window.innerHeight / 2); 333 334 livestreamAnimation.seek(livestreamAnimationProgress * livestreamAnimation.duration) 335 336 // latest news - replaced with snap function 337 updateLatestNewsInScrollHandler(); 338 } 339 340 // Replacement for the latest news section in handleScrollAnimations 341 const updateLatestNewsInScrollHandler = () => { 342 const latestNews = document.querySelector('.sn_block.sn_block_latest_news'); 343 if (!latestNews) return; 344 345 const latestNewsTop = latestNews.getBoundingClientRect().top; 346 const latestNewsAnimationProgress = getScrollProgress( 347 latestNewsTop, 348 -(latestNews.getBoundingClientRect().height - window.innerHeight), 349 topOffset 350 ); 351 352 // Call our snap function 353 latestNewsAnimation(); 354 355 // Keep the card rotations 356 latestNewsCardOdd.seek(latestNewsAnimationProgress * latestNewsCardOdd.duration); 357 latestNewsCardEven.seek(latestNewsAnimationProgress * latestNewsCardEven.duration); 358 }; 359 360 // fully in or above viewport 361 function onAboveBottomChange(element, onAbove, onBelow, useTopReference = true, offset = 150) { 362 let isAbove = false;
363 364 function checkPosition() { 365 if(!element) 366 return; 367 368 const rect = element.getBoundingClientRect(); 369 370 if(useTopReference) { 371 if (rect.top < offset + 130 && !isAbove) { 372 isAbove = true; 373 onAbove(); 374 } else if (rect.top >= offset + 130 && isAbove) { 375 isAbove = false; 376 onBelow(); 377 } 378 } 379 else 380 { 381 if (rect.bottom < window.innerHeight - offset && !isAbove) { 382 isAbove = true; 383 onAbove(); 384 } else if (rect.bottom >= window.innerHeight - offset && isAbove) { 385 isAbove = false; 386 onBelow(); 387 } 388 } 389 } 390 391 window.addEventListener('scroll', checkPosition); 392 window.addEventListener('resize', checkPosition); 393 394 checkPosition(); 395 } 396 397 // social gallery animation trigger 398 if(!isMobile) { 399 onAboveBottomChange(document.querySelector('.sn_block.sn_block_social_gallery'), 400 () => handleSocialGalleryTimeline(), 401 () => handleSocialGalleryTimeline(true) 402 ); 403 } 404 405 // #endregion 406 407 // #region SCROLL TO SECTION 408 409 410 const goToLiveStreamCtas = document.querySelectorAll('.sn_block_t
410icket_countdown-banner .countdown-wrapper-inner'); 411 if (goToLiveStreamCtas){ 412 413 goToLiveStreamCtas.forEach(goToLiveStreamCta => { 414 415 goToLiveStreamCta.addEventListener('click', (e) => { 416 417 e.preventDefault(); 418 // Keep the ticket animation 419 handleTicketTimeline(false); 420 421 // Remove the delay and scroll immediately 422 document.body.classList.remove('scroll-locked'); 423 const liveStreamingBB = document.querySelector('[data-name="shopify-product-slider"]'); 424 console.log(liveStreamingBB); 425 426 if (liveStreamingBB) { 427 // Immediate scroll to the element without waiting 4 seconds 428 liveStreamingBB.scrollIntoView({ behavior: 'smooth', block: 'start' }); 429 } 430 handleScrollAnimations(); 431 }) 432 433 }); 434 435 } 436 437 const goToDayClubCta = document.querySelector('.ticket-side-ctas__item:first-child'); 438 if (goToDayClubCta){ 439 goToDayClubCta.addEventListener('click', (e) => { 440 e.preventDefault(); 441 handleTicketTimeline(false); 442 handleScrollAnimations(); 443 window.scrollTo(0,0); 444 445 setTimeout(() => { 446 document.body.classList.remove('scroll-locked'); 447 }, 4000); 448 }) 449 450 } 451 452 const goToSectionLastCta = document.querySelector('.ticket-side-ctas__item:last-child'); 453 if (goToSectionLastCta){ 454 let goToSectionAttr = goToSectionLastCta.getAttribute('go-to'); 455 goToSectionLastCta.addEventListener('click', (e) => { 456 457 e.preventDefault(); 458 handleTicketTimeline(false); 459 460 if(!goToSectionAttr) { 461 goToSectionAttr = "image-carousel"; 462 } 463 document.body.classList.remove('scroll-locked'); 464 const goToSectionBB = document.querySelector('[data-name="'+goToSectionAttr+'"]'); 465 if (goToSectionBB) { 466 goToSectionBB.scrollIntoView({ behavior: 'smooth', block: 'start' }); 467 } 468 handleScrollAnimations(); 469 }) 470 471 } 472 // #endregion 473 474 // // #region SOCIAL GALLERY MOBILE 475 476 // const playSocialGalleryImageAnimation = (imageElement) => { 477 // anime({ 478 // targets: imageElement, 479 // scale: [0, 1], 480 // easing: 'easeInOutQuad' 481 // }) 482 // } 483 484 // const playSocialGalleryImageAnimationReverse = (imageElement) => { 485 // anime({ 486 // targets: imageElement, 487 // scale: [1, 0], 488 // easing: 'easeInOutQuad' 489 // }) 490 // } 491 492 // if(isMobile) { 493 // const socialGalleryImageElements = document.querySelectorAll('.swe_post_container'); 494 // for (let i = 0; i < socialGalleryImageElements.length; i++) { 495 // onAboveBottomChange(socialGalleryImageElements[i], 496 // () => playSocialGalleryImageAnimation(`.swe_post:nth-child(${i + 1}) .swe_post_container`), 497 // () => playSocialGalleryImageAnimationReverse(`.swe_post:nth-child(${i + 1}) .swe_post_container`), 498 // false, 499 // -100 500 // ); 501 // } 502 // } 503 504 // // #endregion 505 506 // #region SHOP 507 508 const handleShopActivation = (activate = true) => { 509 if(activate) 510 document.querySelector('.sn_block_shopify_product_slider')?.classList.add('active'); 511 else 512 document.querySelector('.sn_block_shopify_product_slider')?.classList.remove('active'); 513 } 514 515 if(!isMobile) { 516 onAboveBottomChange(document.querySelector('.sn_block.sn_block_shopify_product_slider'), 517 () => handleShopActivation(), 518 () => handleShopActivation(false) 519 ); 520 } else { 521 onAboveBottomChange(document.querySelector('.sn_block.sn_block_shopify_product_slider'), 522 () => handleShopActivation(), 523 () => handleShopActivation(false), 524 false, 525 -200 526 ); 527 } 528 529 // #endregion 530 531 // #region QUIZ 532 533 const quizElement = document.querySelector('.sn_block_quiz_wr'); 534 535 const playQuizAnimation = () => { 536 anime({ 537 targets: quizElement, 538 translateY: ['50%', '0%'], 539 easing: 'easeInOutQuad' 540 }) 541 } 542 543 const playQuizAnimationReverse = () => { 544 anime({ 545 targets: quizElement, 546 translateY: ['0%', '50%'], 547 easing: 'easeInOutQuad' 548 }) 549 } 550 551 onAboveBottomChange(document.querySelector('.sn_block_quiz.sn_block'), 552 () => playQuizAnimation(), 553 () => playQuizAnimationReverse() 554 ); 555 556 // #endregion 557 558 // #region SPOTIFY 559 560 const spotifyElement = document.querySelector('.sn_block_spotify_playlist_wr iframe'); 561 const spotifyElementLets = document.querySelector('.sn_block_spotify_playlist_wr .lets .content'); 562 const spotifyElementPlay = document.querySelector('.sn_block_spotify_playlist_wr .play .content'); 563 564 const playSpotifyAnimation = () => { 565 anime({ 566 targets: spotifyElement, 567 translateX: ['90%', '0%'], 568 translateY: ['80%', '0%'], 569 rotate: ['-16deg', '0deg'], 570 easing: 'easeInOutQuad' 571 }) 572 anime ({ 573 targets: spotifyElementLets, 574 translateX: ['-100%', '0%'], 575 easing: 'easeInOutQuad' 576 }) 577 anime ({ 578 targets: spotifyElementPlay, 579 translateX: ['100%', '0%'], 580 easing: 'easeInOutQuad' 581 }) 582 } 583 584 const playSpotifyAnimationReverse = () => { 585 anime({ 586 targets: spotifyElement, 587 translateX: ['0%', '90%'], 588 translateY: ['0%', '80%'], 589 rotate: ['0deg', '-16deg'], 590 easing: 'easeInOutQuad' 591 }) 592 anime ({ 593 targets: spotifyElementLets, 594 translateX: ['0%', '-100%'], 595 easing: 'easeInOutQuad' 596 }) 597 anime ({ 598 targets: spotifyElementPlay, 599 translateX: ['0%', '100%'], 600 easing: 'easeInOutQuad' 601 }) 602 } 603 604 onAboveBottomChange(document.querySelector('.sn_block.sn_block_spotify_playlist'), 605 () => playSpotifyAnimation(), 606 () => playSpotifyAnimationReverse() 607 ); 608 609 // #endregion 610 611 // #region PROGRESS BAR 612 613 const progressBarParent = document.querySelector('.progress-bar'); 614 const progressBar = document.querySelector('.progress-bar-fill'); 615 616 const blocks = Array.from(document.querySelectorAll('.sn_site_wrapper .sn_block')); 617 blocks.shift(); 618 blocks.shift(); 619 blocks.shift(); 620 621 blocks.forEach(block => { 622 const progressBarRepeatElement = document.createElement('div'); 623 progressBarRepeatElement.classList.add('progress-bar-section'); 624 progressBarParent.appendChild(progressBarRepeatElement); 625 }) 626 627 const updateProgressBar = () => { 628 const progressBarProgress = () => { 629 const lastBlock = blocks[blocks.length - 1]; 630 const lastBlockRectBottom = lastBlock ? lastBlock.getBoundingClientRect().bottom : 0; 631 632 const barLength = window.innerWidth / blocks.length; 633 634 for(let i = 0; i < blocks.length; i++) { 635 const currentBlock = blocks[i]; 636 const currentBlockBottom = currentBlock ? currentBlock.getBoundingClientRect().bottom : 0; 637 const currentBlockHeight = currentBlock ? currentBlock.getBoundingClientRect().height : 0; 638 const nextBlock = blocks[i + 1]?.getBoundingClientRect(); 639 640 if (currentBlockBottom > window.innerHeight) { 641 const progress = getScrollProgress(currentBlockBottom, window.innerHeight, window.innerHeight + currentBlockHeight) * barLength; 642 if (!nextBlock || nextBlock.top >= window.innerHeight) { 643 return (barLength * i) + progress; 644 } 645 } 646 } 647 648 return lastBlockRectBottom < window.innerHeight ? window.innerWidth : barLength; 649 } 650 651 progressBar.style.width = progressBarProgress() + 'px'; 652 653 } 654 655 // #endregion 656 657 // Add window resize handler to recalculate positions 658 window.addEventListener('resize', () => { 659 // Reset current position on resize to prevent out-of-bounds 660 const { totalPositions } = calculateSlidePositions(); 661 currentSnapPosition = Math.min(currentSnapPosition, totalPositions); 662 latestNewsAnimation(); 663 }); 664 665 updateProgressBar(); 666 window.onscroll = () => { 667 updateProgressBar(); 668 handleScrollAnimations(); 669 } 670 671 // #region SLIDER WHEEL 672 673 const tiles = document.querySelectorAll('.carousel-card'); 674 const radius = isMobile ? 1575 : 2000; // Raggio più grande
675 let currentIndex = 0; 676 677 function updatePositions() { 678 const centerX = window.innerWidth / 2; 679 const angleStep = Math.PI / 18; // 15 gradi 680 681 tiles.forEach((tile, index) => { 682 const relativeIndex = ((index - currentIndex) + tiles.length) % tiles.length; 683 const adjustedIndex = relativeIndex - Math.floor(tiles.length / 2); 684 685 // Calcola l'angolo rispetto alla verticale 686 const angle = adjustedIndex * angleStep; 687 688 // Posizione sulla circonferenza 689 const x = centerX + Math.sin(angle) * radius; 690 const y = radius - Math.cos(angle) * radius; 691 692 // Rotazione allineata al raggio 693 const rotation = angle * (180 / Math.PI); 694 695 // Opacità basata sulla distanza dal centro 696 const opacity = Math.abs(adjustedIndex) > 2 ? 0 : 1; 697 698 tile.style.transform = `translate(${x}px, ${y}px) rotate(${rotation}deg)`; 699 tile.style.opacity = opacity; 700 tile.style.zIndex = 10 - Math.abs(adjustedIndex); 701 }); 702 } 703 704 function slide() { 705 currentIndex = (currentIndex + 1) % tiles.length; 706 updatePositions(); 707 } 708 709 // Posizionamento iniziale 710 updatePositions(); 711 712 // Autoplay 713 setInterval(slide, 3000); 714 715 // Aggiorna posizioni al ridimensionamento 716 window.addEventListener('resize', updatePositions); 717 718 // #endregion 719 720 // #region SLIDER LINEAR 721 722 // const track = document.querySelector('.slider-track'); 723 // const tilesLinear = document.querySelectorAll('.news_card'); 724 725 // let currentIndexLinear = 0; 726 // let startX = 0; 727 // let currentX = 0; 728 // let isDragging = false; 729 // let startTime = 0; 730 // let dragThreshold = 50; // Soglia minima di trascinamento per cambiare slide 731 732 // // Clona gli elementi per il loop infinito 733 // function cloneElements() { 734 // const visibleSlides = getVisibleSlides();
735 // const slidesToClone = Math.ceil(visibleSlides); 736 737 // // Clona elementi all'inizio e alla fine 738 // tilesLinear.forEach((tile, index) => { 739 // if (index < slidesToClone) { 740 // const endClone = tile.cloneNode(true); 741 // if (track){ 742 // track.appendChild(endClone); 743 // } 744 // } 745 // if (index >= tilesLinear.length - slidesToClone) { 746 // const startClone = tile.cloneNode(true); 747 // if (track){ 748 // track.insertBefore(startClone, track.firstChild); 749 // } 750 // } 751 // }); 752 753 // // Imposta la posizione iniziale per mostrare le slide originali 754 // currentIndexLinear = slidesToClone; 755 // updateSliderPosition(false); 756 // } 757 758 // function getVisibleSlides() { 759 // const width = window.innerWidth; 760 // if (width <= 767) return 1.25; 761 // if (width <= 1023) return 2.5; 762 // return 4; 763 // } 764 765 // function getTileWidth() { 766 // const tile = document.querySelector('.news_card'); 767 // if (!tile) return; 768 // return tile.offsetWidth + parseInt(getComputedStyle(tile).marginLeft) * 2; 769 // } 770 771 // function updateSliderPosition(animate = true) { 772 // const translateX = -currentIndexLinear * getTileWidth(); 773 // if (track){ 774 // track.style.transition = animate ? 'transform 0.3s ease-out' : 'none'; 775 // track.style.transform = `translateX(${translateX}px)`; 776 // } 777 // } 778 779 // function next() { 780 // currentIndexLinear++; 781 // updateSliderPosition(); 782 // checkBoundary(); 783 // } 784 785 // function prev() { 786 // currentIndexLinear--; 787 // updateSliderPosition(); 788 // checkBoundary(); 789 // } 790 791 // function checkBoundary() { 792 // if (!track) return; 793 794 // const totalSlides = track.children.length; 795 // const visibleSlides = getVisibleSlides(); 796 797 // // Reset alla fine del loop 798 // track.addEventListener('transitionend', () => { 799 // if (currentIndexLinear >= totalSlides - Math.ceil(visibleSlides)) { 800 // currentIndexLinear = Math.ceil(visibleSlides); 801 // updateSliderPosition(false); 802 // } else if (currentIndexLinear <= 0) { 803 // currentIndexLinear = totalSlides - Math.ceil(visibleSlides) - 1; 804 // updateSliderPosition(false); 805 // } 806 // }, { once: true }); 807 // } 808 809 // function handleDragStart(e) { 810 // isDragging = true; 811 // startX = e.type.includes('mouse') ? e.pageX : e.touches[0].pageX; 812 // startTime = Date.now(); 813 // if (track){ 814 // track.classList.add('dragging'); 815 // } 816 // } 817 818 // function handleDragMove(e) { 819 // if (!isDragging) return; 820 // e.preventDefault(); 821 822 // currentX = e.type.includes('mouse') ? e.pageX : e.touches[0].pageX; 823 // const diff = currentX - startX; 824 825 // // Applica il movimento durante il drag 826 // const translateX = -currentIndexLinear * getTileWidth() + diff; 827 // if (track){ 828 // track.style.transform = `translateX(${translateX}px)`; 829 // } 830 // } 831 832 // function handleDragEnd() { 833 // if (!isDragging) return; 834 835 // const dragDuration = Date.now() - startTime; 836 // const dragDistance = currentX - startX; 837 838 // // Determina se cambiare slide in base alla distanza o velocità del drag 839 // if (Math.abs(dragDistance) > dragThreshold || (Math.abs(dragDistance) > 20 && dragDuration < 200)) { 840 // if (dragDistance > 0) { 841 // prev(); 842 // } else { 843 // next(); 844 // } 845 // } else { 846 // // Torna alla posizione originale se il drag non è sufficiente 847 // updateSliderPosition(); 848 // } 849 850 // isDragging = false; 851 // if (track){ 852 // track.classList.remove('dragging'); 853 // } 854 // } 855 856 // // Event Listeners 857 // if (track){ 858 // track.addEventListener('mousedown', handleDragStart); 859 // track.addEventListener('touchstart', handleDragStart); 860 // track.addEventListener('mousemove', handleDragMove); 861 // track.addEventListener('touchmove', handleDragMove); 862 // track.addEventListener('mouseup', handleDragEnd); 863 // track.addEventListener('touchend', handleDragEnd); 864 // track.addEventListener('mouseleave', handleDragEnd); 865 // } 866 867 // // Inizializzazione 868 // cloneElements(); 869 870 // // Gestione del resize 871 // let resizeTimeout; 872 // window.addEventListener('resize', () => { 873 // clearTimeout(resizeTimeout); 874 // resizeTimeout = setTimeout(() => { 875 // updateSliderPosition(false); 876 // }, 100); 877 // }); 878 879 // // Configurazione slider 880 // const sliderConfig = { 881 // autoplay: true, // abilita/disabilita autoplay 882 // autoplaySpeed: 300000000, // velocità autoplay in ms 883 // pauseOnHover: true // pausa autoplay al passaggio del mouse 884 // }; 885 886 // // Gestione autoplay 887 // let autoplayInterval; 888 889 // function startAutoplay() {
890 // if (sliderConfig.autoplay) { 891 // autoplayInterval = setInterval(next, sliderConfig.autoplaySpeed); 892 // } 893 // } 894 895 // function stopAutoplay() { 896 // clearInterval(autoplayInterval); 897 // } 898 899 // // Gestione pause on hover 900 // if (sliderConfig.pauseOnHover) { 901 // if (track){ 902 // track.addEventListener('mouseenter', stopAutoplay); 903 // track.addEventListener('mouseleave', startAutoplay); 904 // } 905 // } 906 907 // Avvia autoplay se abilitato 908 // startAutoplay(); 909 910 // #endregion 911});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.