Игровой автомат "Слоты"

Модификатор позволяет создать игру "Слоты" для вашего сайта на Тильде
Только для Club
Инструкция по настройке
Шаблон страницы
Как добавить шаблон
94800596
Для корректной работы модификаций подключите библиотеку jQuery:
Настройки сайта -> Еще -> Подключить jQuery на страницах сайта
jQuery
Создаем Zero Block и открываем редактор
  1. Добавляем 3 шейпа для слотов.
  2. Задаем им классы random-image1, random-image2, random-image3
  3. Задаем им одинаковые размеры
  4. Загружаем в них изображения, они будут видны до запуска
  5. Добавляем кнопку для запуска игры
  6. Задаем ей класс random-image-btn-start
1 шаг
Создаем поп-апы с призами
  1. При выигрыше (когда одинаковые картинки выпадают в слотах) будет открываться поп-ап. Для этого:
  2. Создаем 3 блока BF503 или любые другие поп-ап блоки
  3. Задаем им адреса #popup1, #popup2, #popup3
2 шаг
Создаем блок T123 и копируем в него код
3 шаг
Скопировать код
Настраиваем код
  1. На 123-125 строках меняем ссылки на картинки в барабанах
  2. На 129-131 строках дублируем ссылки в том же порядке и пишем адрес поп-ап окна, без #
4 шаг
<!--TS28 - Модификация для Тильды. Игровой автомат "Слоты" https://mod.tistols.com/slots -->

<style>.random-image-btn-start {cursor: pointer;}</style>
<script>
function injectSlotStyles() {
  if (document.getElementById('slot-roller-styles')) return;
  const el = document.createElement('style');
  el.id = 'slot-roller-styles';
  el.textContent = `
    .slot-reel { position: relative; overflow: hidden; }
    .slot-roller { position: absolute; inset: 0; z-index: 2; pointer-events: none; }
    .slot-item { height: 100%; background-size: cover; background-position: center; }
    .none-block { display: none !important; }
  `;
  document.head.appendChild(el);
}

function startReelSpin(reelEl, allUrls, finalUrl, durationMs) {
  reelEl.classList.add('slot-reel');
  const roller = document.createElement('div');
  roller.className = 'slot-roller';

  const count = Math.max(8, Math.floor(durationMs / 120));
  for (let i = 0; i < count; i++) {
    const url = allUrls[Math.floor(Math.random() * allUrls.length)];
    const item = document.createElement('div');
    item.className = 'slot-item';
    item.style.backgroundImage = `url('${url}')`;
    item.style.backgroundSize = 'contain';
    item.style.backgroundPosition = 'center';
    item.style.backgroundRepeat = 'no-repeat';
    roller.appendChild(item);
  }

  // Финальный кадр (куда плавно «докручиваем»)
  const last = document.createElement('div');
  last.className = 'slot-item';
  last.style.backgroundImage = `url('${finalUrl}')`;
  last.style.backgroundSize = 'contain';
  last.style.backgroundPosition = 'center';
  last.style.backgroundRepeat = 'no-repeat';
  roller.appendChild(last);

  reelEl.appendChild(roller);
  roller.getBoundingClientRect(); 

  const h = reelEl.clientHeight || reelEl.offsetHeight;
  const totalItems = roller.children.length;

  // Плавное замедление
  roller.style.transition = `transform ${durationMs}ms cubic-bezier(.2,.8,.2,1)`;
  roller.style.transform = `translateY(-${(totalItems - 1) * h}px)`;

  // Очистка
  return () => {
    roller.remove();
    reelEl.classList.remove('slot-reel');
  };
}

// ткрытие поп-апа вида #popup1 / #popup2 / #popup3
function openTildaPopup(hookName) {
  const hash = `#${hookName}`;

  // 0) если есть API Тильды
  if (typeof window.t_popup__open === 'function') {
    window.t_popup__open(hash);
    return true;
  }
  if (typeof window.t390_showPopup === 'function') {
    const el = document.querySelector(`[data-tooltip-hook="${hash}"]`);
    const rec = el && el.closest('[id^="rec"]');
    if (rec) { window.t390_showPopup(rec.id.replace('rec','')); return true; }
  }

  // 1) Прямое открытие по DOM
  let popup = document.querySelector(`.t-popup[data-tooltip-hook="${hash}"]`);
  if (!popup) {
    const anyHookEl = document.querySelector(`[data-tooltip-hook="${hash}"]`);
    if (anyHookEl) popup = anyHookEl.closest('.t-popup');
  }
  if (popup) {
    popup.style.display = 'block';
    popup.classList.add('t-popup_show');
    document.body.classList.add('t-body_popupshowed');
    const container = popup.querySelector('.t-popup__container');
    if (container) container.setAttribute('tabindex','-1');
    return true;
  }

  // 2) Временный триггер + клик
  const a = document.createElement('a');
  a.href = hash;
  a.setAttribute('data-tooltip-hook', hash);
  Object.assign(a.style, {position:'fixed',left:'-9999px',top:'-9999px',width:'1px',height:'1px',opacity:'0'});
  document.body.appendChild(a);
  a.click();
  setTimeout(() => { a.click(); a.remove(); }, 30);

  // 3) Fallback: hashchange
  setTimeout(() => {
    if (location.hash === hash) {
      history.replaceState(null, '', location.pathname + location.search);
    }
    location.hash = hash;
    try {
      window.dispatchEvent(new HashChangeEvent('hashchange'));
    } catch (_) {
      const ev = document.createEvent('HashChangeEvent');
      ev.initEvent('hashchange', true, true);
      window.dispatchEvent(ev);
    }
  }, 60);

  return true;
}

// =====================
// Класс SlotMachine
// =====================
class SlotMachine {
  constructor() {
    this.lastResult = [];

    this.instruments = [
      ['Подарок', 'https://static.tildacdn.com/tild3538-3762-4664-a430-363334353534/4242545452343_1.png'],
      ['Игрушка', 'https://static.tildacdn.com/tild6231-6339-4537-b265-396165323565/4242545452343_2.png'],
      ['Карта', 'https://static.tildacdn.com/tild3162-3265-4234-b531-333033363735/4242545452343_3.png']
    ];

    this.POPUPS = {
      'https://static.tildacdn.com/tild3538-3762-4664-a430-363334353534/4242545452343_1.png': 'popup1',
      'https://static.tildacdn.com/tild6231-6339-4537-b265-396165323565/4242545452343_2.png': 'popup2',
      'https://static.tildacdn.com/tild3162-3265-4234-b531-333033363735/4242545452343_3.png': 'popup3'
    };

    this.reels = [
      document.querySelector('.random-image1'),
      document.querySelector('.random-image2'),
      document.querySelector('.random-image3')
    ].filter(Boolean);

    // Оставил ссылку на любую «повторить» кнопку
    this.spinButtonRepeat = document.querySelector('.random-image-btn-start-repeat');

    this.isSpinning = false;

    this.instrumentElements = [
      document.querySelector('.random-name1'),
      document.querySelector('.random-name2'),
      document.querySelector('.random-name3')
    ];

    this.setInitialImages();
    this.bindEvents();
    injectSlotStyles();
  }

  getRandomItem(arr) {
    return arr[Math.floor(Math.random() * arr.length)];
  }

  setInitialImages() {
    const picks = this.reels.map(() => this.getRandomItem(this.instruments));
    this.lastResult = picks;

    this.reels.forEach((reel, idx) => {
      const instum = picks[idx];
      const target = reel.querySelector('.tn-atom') || reel;
      target.style.backgroundImage = `url('${instum[1]}')`;
      target.style.backgroundSize = 'contain';
      target.style.backgroundPosition = 'center';
      target.style.backgroundRepeat = 'no-repeat';
      if (this.instrumentElements[idx]) {
        this.instrumentElements[idx].textContent = instum[0];
      }
    });
  }

  bindEvents() {
    // Любая кнопка .random-image-btn-start запускает барабаны
    document.querySelectorAll('.random-image-btn-start').forEach(btn => {
      btn.addEventListener('click', () => {
        if (!this.isSpinning) this.spin();
      });
    });

    if (this.spinButtonRepeat)
      this.spinButtonRepeat.addEventListener('click', () => {
        if (!this.isSpinning) this.spin();
      });
  }

  spin() {
    // Скрываем все старт-кнопки на время спина (чтобы не спамили)
    document.querySelectorAll('.random-image-btn-start').forEach(b => b.classList.add('none-block'));

    this.reels.forEach(reel => {
      const target = reel.querySelector('.tn-atom') || reel;
      target.style.backgroundImage = 'none';
    });

    this.isSpinning = true;

    // Независимый рандом для каждого барабана
    const picks = this.reels.map(() => this.getRandomItem(this.instruments));
    this.lastResult = picks;

    const allUrls = this.instruments.map(x => x[1]);

    // --- ВАЖНО: нужные длительности остановки ---
    const durations = [2000, 3000, 4500]; // 1-й, 2-й, 3-й барабан

    const cleaners = [];
    this.reels.forEach((reel, index) => {
      const instum = picks[index];
      const finalUrl = instum[1];
      const target = reel.querySelector('.tn-atom') || reel;

      const duration = durations[index] || durations[durations.length - 1];
      const cleanup = startReelSpin(target, allUrls, finalUrl, duration);
      cleaners.push({ cleanup, target, finalUrl, name: instum[0] });
    });

    const totalWait = Math.max(...durations) + 80;

    setTimeout(() => {
      cleaners.forEach(({ cleanup, target, finalUrl }, idx) => {
        cleanup();
        target.style.backgroundImage = `url('${finalUrl}')`;
        target.style.backgroundSize = 'contain';
        target.style.backgroundPosition = 'center';
        target.style.backgroundRepeat = 'no-repeat';
        if (this.instrumentElements[idx]) {
          const found = this.instruments.find(i => i[1] === finalUrl);
          if (found) this.instrumentElements[idx].textContent = found[0];
        }
      });

      this.isSpinning = false;

      // Возвращаем старт-кнопки
      document.querySelectorAll('.random-image-btn-start').forEach(b => b.classList.remove('none-block'));

      // Проверка совпадений: все 3 одинаковые
      const urls = this.lastResult.map(x => x[1]);
      const allSame = urls.length > 0 && urls.every(u => u === urls[0]);
      if (allSame) {
        const popupHook = this.POPUPS[urls[0]]; // 'popup1' | 'popup2' | 'popup3'
        if (popupHook) setTimeout(() => openTildaPopup(popupHook), 100);
      }
    }, totalWait);
  }
}

document.addEventListener('DOMContentLoaded', () => {
  new SlotMachine();
});
</script>
Вам также может быть интересно: