oscarviedma

JavaScript Sección ToonHub

Jun 12th, 2026
180
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
HTML 9.54 KB | None | 0 0
  1. <script>
  2. (function () {
  3.  
  4.   /* ══════════════════════════════════════════
  5.      ✏️  EDITA AQUÍ TUS SLIDES
  6.      Puedes agregar o quitar los que necesites
  7.      ══════════════════════════════════════════ */
  8.   var SLIDES = [
  9.     {
  10.       src   : 'https://fifth-gentle-45902158.figma.site/_components/v2/4de492f6d9cf8244ad5293233e5c6f52407d42fc/1.02464a56.png',
  11.       bg    : '#F4845F',
  12.       ghost : 'FUEGO',
  13.       title : 'EDICIÓN FUEGO',
  14.       desc  : 'La obra de arte es impresionante, se envía completamente preparada. El acabado es espectacular, la impresión 3D es impecable. ¡Haz tu pedido ahora!',
  15.       link  : '#',
  16.     },
  17.     {
  18.       src   : 'https://fifth-gentle-45902158.figma.site/_components/v2/4de492f6d9cf8244ad5293233e5c6f52407d42fc/2.b977faab.png',
  19.       bg    : '#6BBF7A',
  20.       ghost : 'NATURALEZA',
  21.       title : 'EDICIÓN NATURALEZA',
  22.       desc  : 'Colores vibrantes directos de la selva. Figura premium con acabado mate resistente. Edición limitada. ¡No te quedes sin la tuya!',
  23.       link  : '#',
  24.     },
  25.     {
  26.       src   : 'https://fifth-gentle-45902158.figma.site/_components/v2/4de492f6d9cf8244ad5293233e5c6f52407d42fc/3.4df853b4.png',
  27.       bg    : '#E882B4',
  28.       ghost : 'MAGIA',
  29.       title : 'EDICIÓN MAGIA',
  30.       desc  : 'Un diseño que hipnotiza. Detalles pintados a mano con acabado glossy de alta calidad. La favorita de la colección.',
  31.       link  : '#',
  32.     },
  33.     {
  34.       src   : 'https://fifth-gentle-45902158.figma.site/_components/v2/4de492f6d9cf8244ad5293233e5c6f52407d42fc/4.4457fbce.png',
  35.       bg    : '#6EB5FF',
  36.       ghost : 'CIELO',
  37.       title : 'EDICIÓN CIELO',
  38.       desc  : 'Elevada por encima del resto. Materiales premium, empaque listo para regalo. Diseño exclusivo de temporada.',
  39.       link  : '#',
  40.     },
  41.   ];
  42.  
  43.   /* ══ ESTADO ══ */
  44.   var N           = SLIDES.length;
  45.   var activeIndex = 0;
  46.   var isAnimating = false;
  47.   var isMobile    = window.innerWidth < 640;
  48.  var hintTimer   = null;
  49.  
  50.  /* ══ DRAG / SWIPE ══ */
  51.  var dragStartX     = null;
  52.  var dragStartY     = null;
  53.  var isDragging     = false;
  54.  var DRAG_THRESHOLD = 50;
  55.  
  56.  /* ══ REFS DOM ══ */
  57.  var wrap     = document.getElementById('ov-th-wrap');
  58.  var ghost    = document.getElementById('ov-th-ghost');
  59.  var title    = document.querySelector('.ov-th-title');
  60.  var desc     = document.querySelector('.ov-th-desc');
  61.  var stage    = document.getElementById('ov-th-stage');
  62.  var discover = document.getElementById('ov-th-discover');
  63.  var hint     = document.getElementById('ov-th-hint');
  64.  
  65.  /* ══ GRAIN ══ */
  66.  var svgNoise = "<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/></filter><rect width='200' height='200' filter='url(%23n)' opacity='0.08'/></svg>";
  67.   document.getElementById('ov-th-grain').style.backgroundImage =
  68.     "url(\"data:image/svg+xml," + encodeURIComponent(svgNoise) + "\")";
  69.  
  70.   /* ══ ROLES ══ */
  71.   function getRoleMap(idx) {
  72.     var m = {};
  73.     m[idx]           = 'center';
  74.     m[(idx+N-1) % N] = 'left';
  75.     m[(idx+1)   % N] = 'right';
  76.     m[(idx+2)   % N] = 'back';
  77.     /* slides extra → hidden (para cuando N > 4) */
  78.     for (var i = 0; i < N; i++) {
  79.      if (!m[i]) m[i] = 'hidden';
  80.    }
  81.    return m;
  82.  }
  83.  
  84.  /* ══ ESTILOS POR ROL ══ */
  85.  function getStyle(role) {
  86.    if (role === 'center') return {
  87.      transform : 'translateX(-50%) scale(' + (isMobile ? 1.25 : 1.68) + ')',
  88.      filter    : 'none', opacity: '1', zIndex: '20',
  89.      left      : '50%',
  90.      height    : isMobile ? '60%' : '92%',
  91.      bottom    : isMobile ? '22%' : '0',
  92.    };
  93.    if (role === 'left') return {
  94.      transform : 'translateX(-50%) scale(1)',
  95.      filter    : 'blur(2px)', opacity: '0.85', zIndex: '10',
  96.      left      : isMobile ? '20%' : '30%',
  97.      height    : isMobile ? '16%' : '28%',
  98.      bottom    : isMobile ? '32%' : '12%',
  99.    };
  100.    if (role === 'right') return {
  101.      transform : 'translateX(-50%) scale(1)',
  102.      filter    : 'blur(2px)', opacity: '0.85', zIndex: '10',
  103.      left      : isMobile ? '80%' : '70%',
  104.      height    : isMobile ? '16%' : '28%',
  105.      bottom    : isMobile ? '32%' : '12%',
  106.    };
  107.    if (role === 'back') return {
  108.      transform : 'translateX(-50%) scale(1)',
  109.      filter    : 'blur(4px)', opacity: '1', zIndex: '5',
  110.      left      : '50%',
  111.      height    : isMobile ? '13%' : '22%',
  112.      bottom    : isMobile ? '32%' : '12%',
  113.    };
  114.    /* hidden — slides extra cuando N > 4 */
  115.     return {
  116.       transform : 'translateX(-50%) scale(0.8)',
  117.       filter    : 'blur(6px)', opacity: '0', zIndex: '1',
  118.       left      : '50%',
  119.       height    : '15%',
  120.       bottom    : '10%',
  121.     };
  122.   }
  123.  
  124.   /* ══ APLICAR ESTILOS ══ */
  125.   function applyStyles() {
  126.     wrap.style.backgroundColor = SLIDES[activeIndex].bg;
  127.     var roleMap = getRoleMap(activeIndex);
  128.     document.querySelectorAll('.ov-th-item').forEach(function (item, i) {
  129.       var s = getStyle(roleMap[i]);
  130.       item.style.transform = s.transform;
  131.       item.style.filter    = s.filter;
  132.       item.style.opacity   = s.opacity;
  133.       item.style.zIndex    = s.zIndex;
  134.       item.style.left      = s.left;
  135.       item.style.height    = s.height;
  136.       item.style.bottom    = s.bottom;
  137.     });
  138.   }
  139.  
  140.   /* ══ ACTUALIZAR TEXTOS (fade) ══ */
  141.   function updateText() {
  142.     var slide = SLIDES[activeIndex];
  143.     ghost.style.opacity = '0';
  144.     title.style.opacity = '0';
  145.     desc.style.opacity  = '0';
  146.     setTimeout(function () {
  147.       ghost.textContent   = slide.ghost;
  148.       title.textContent   = slide.title;
  149.       desc.textContent    = slide.desc;
  150.       discover.href       = slide.link;
  151.       ghost.style.opacity = '1';
  152.       title.style.opacity = '0.95';
  153.       desc.style.opacity  = '0.85';
  154.     }, 200);
  155.   }
  156.  
  157.   /* ══ NAVEGAR ══ */
  158.   function navigate(dir) {
  159.     if (isAnimating) return;
  160.     isAnimating = true;
  161.     activeIndex = dir === 'next' ? (activeIndex+1) % N : (activeIndex+N-1) % N;
  162.     applyStyles();
  163.     updateText();
  164.     setTimeout(function () { isAnimating = false; }, 650);
  165.   }
  166.  
  167.   /* ══ CONSTRUIR ITEMS ══ */
  168.   SLIDES.forEach(function (data, i) {
  169.     var item = document.createElement('div');
  170.     item.className = 'ov-th-item';
  171.     var img = document.createElement('img');
  172.     img.src       = data.src;
  173.     img.alt       = data.title;
  174.     img.draggable = false;
  175.     item.appendChild(img);
  176.     stage.appendChild(item);
  177.   });
  178.  
  179.   /* ══ INIT ══ */
  180.   applyStyles();
  181.   ghost.textContent = SLIDES[0].ghost;
  182.   title.textContent = SLIDES[0].title;
  183.   desc.textContent  = SLIDES[0].desc;
  184.   discover.href     = SLIDES[0].link;
  185.  
  186.   /* ══ BOTONES ══ */
  187.   document.getElementById('ov-th-prev').addEventListener('click', function (e) {
  188.     e.stopPropagation(); navigate('prev');
  189.   });
  190.   document.getElementById('ov-th-next').addEventListener('click', function (e) {
  191.     e.stopPropagation(); navigate('next');
  192.   });
  193.  
  194.   /* ══ TECLADO ══ */
  195.   document.addEventListener('keydown', function (e) {
  196.     if (e.key === 'ArrowRight' || e.key === 'ArrowLeft') {
  197.       e.preventDefault();
  198.       navigate(e.key === 'ArrowRight' ? 'next' : 'prev');
  199.       hint.classList.add('ov-th-visible');
  200.       clearTimeout(hintTimer);
  201.       hintTimer = setTimeout(function () { hint.classList.remove('ov-th-visible'); }, 1500);
  202.     }
  203.   });
  204.  
  205.   /* ══ DRAG (mouse) ══ */
  206.   wrap.addEventListener('mousedown', function (e) {
  207.     if (e.target.closest('.ov-th-btn') || e.target.closest('#ov-th-br')) return;
  208.     dragStartX = e.clientX;
  209.     dragStartY = e.clientY;
  210.     isDragging = false;
  211.     wrap.classList.add('ov-th-dragging');
  212.   });
  213.  
  214.   document.addEventListener('mousemove', function (e) {
  215.     if (dragStartX === null) return;
  216.     if (Math.abs(e.clientX - dragStartX) > 5) isDragging = true;
  217.   });
  218.  
  219.   document.addEventListener('mouseup', function (e) {
  220.     if (dragStartX === null) return;
  221.     var dx = e.clientX - dragStartX;
  222.     if (isDragging && Math.abs(dx) >= DRAG_THRESHOLD) {
  223.      navigate(dx < 0 ? 'next' : 'prev');
  224.     }
  225.     dragStartX = null;
  226.     isDragging = false;
  227.     wrap.classList.remove('ov-th-dragging');
  228.   });
  229.  
  230.   /* ══ SWIPE (touch) ══ */
  231.   wrap.addEventListener('touchstart', function (e) {
  232.     dragStartX = e.touches[0].clientX;
  233.     dragStartY = e.touches[0].clientY;
  234.     isDragging = false;
  235.   }, { passive: true });
  236.  
  237.   wrap.addEventListener('touchmove', function (e) {
  238.     if (dragStartX === null) return;
  239.     var dx = Math.abs(e.touches[0].clientX - dragStartX);
  240.     var dy = Math.abs(e.touches[0].clientY - dragStartY);
  241.     if (dx > dy) { e.preventDefault(); isDragging = true; }
  242.   }, { passive: false });
  243.  
  244.   wrap.addEventListener('touchend', function (e) {
  245.     if (dragStartX === null) return;
  246.     var dx = e.changedTouches[0].clientX - dragStartX;
  247.     if (isDragging && Math.abs(dx) >= DRAG_THRESHOLD) {
  248.      navigate(dx < 0 ? 'next' : 'prev');
  249.     }
  250.     dragStartX = null;
  251.     isDragging = false;
  252.   });
  253.  
  254.   /* ══ PRELOAD ══ */
  255.   SLIDES.forEach(function (d) { var img = new Image(); img.src = d.src; });
  256.  
  257.   /* ══ RESIZE ══ */
  258.   window.addEventListener('resize', function () {
  259.     var nm = window.innerWidth < 640;
  260.    if (nm !== isMobile) { isMobile = nm; applyStyles(); }
  261.  });
  262.  
  263. })();
  264. </script>
Advertisement
Add Comment
Please, Sign In to add comment