<!--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>