mnemo_cards/games/ads_example/assets/vast_player_new.html
2025-11-11 02:55:41 +03:00

405 lines
No EOL
17 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html>
<head>
<title>Vast-Player Example</title>
<script src="https://cdn.jsdelivr.net/npm/vast-player@latest/dist/vast-player.min.js"></script>
<style>
body {
margin: 0;
padding: 0;
background: #000;
font-family: Arial, sans-serif;
}
#container {
width: 100%;
height: 100vh;
position: relative;
display: flex;
justify-content: center;
align-items: center;
}
.loading {
color: white;
text-align: center;
}
.error {
color: #ff6b6b;
text-align: center;
padding: 20px;
}
.ad-info {
position: absolute;
top: 10px;
left: 10px;
color: white;
background: rgba(0,0,0,0.7);
padding: 10px;
border-radius: 5px;
font-size: 12px;
z-index: 1000;
}
.skip-button {
position: absolute;
top: 10px;
right: 10px;
background: rgba(0,0,0,0.8);
color: white;
border: 2px solid white;
border-radius: 20px;
padding: 8px 16px;
font-size: 14px;
font-weight: bold;
cursor: pointer;
z-index: 1001;
display: none;
transition: all 0.3s ease;
}
.skip-button:hover {
background: rgba(255,255,255,0.2);
transform: scale(1.05);
}
.skip-button.visible {
display: block;
}
.skip-timer {
position: absolute;
top: 10px;
right: 10px;
background: rgba(0,0,0,0.8);
color: white;
border: 2px solid #ff6b6b;
border-radius: 20px;
padding: 8px 16px;
font-size: 14px;
font-weight: bold;
z-index: 1001;
display: none;
}
.skip-timer.visible {
display: block;
}
</style>
</head>
<body>
<div id="container">
<div class="loading">Загрузка рекламы...</div>
<button id="skipButton" class="skip-button" onclick="skipAd()">Пропустить рекламу</button>
<div id="skipTimer" class="skip-timer">Пропустить через: <span id="skipTime">5</span>с</div>
</div>
<script>
(function(VASTPlayer) {
'use strict';
var container = document.getElementById('container');
var player = new VASTPlayer(container);
// Элементы для кнопки пропуска
var skipButton = document.getElementById('skipButton');
var skipTimer = document.getElementById('skipTimer');
var skipTimeSpan = document.getElementById('skipTime');
var skipTimerInterval = null;
var skipOffset = 5; // секунд до возможности пропуска (по умолчанию)
var skipOffsetFromVast = null; // будет установлено из VAST данных
// Функция для отправки событий в Flutter
function sendToFlutter(eventName, data) {
console.log('Sending to Flutter:', eventName, data);
if (window.flutter_inappwebview) {
window.flutter_inappwebview.callHandler(eventName, data);
}
}
// Функция для парсинга времени из формата HH:MM:SS
function parseTimeToSeconds(timeString) {
if (!timeString) return 5; // по умолчанию 5 секунд
var parts = timeString.split(':');
if (parts.length === 3) {
var hours = parseInt(parts[0]) || 0;
var minutes = parseInt(parts[1]) || 0;
var seconds = parseInt(parts[2]) || 0;
return hours * 3600 + minutes * 60 + seconds;
}
return 5; // по умолчанию 5 секунд
}
// Функция для получения skipoffset из VAST данных
function getSkipOffsetFromVast() {
try {
// Пытаемся получить skipoffset из VAST данных
if (player && player.vastResponse && player.vastResponse.ads && player.vastResponse.ads.length > 0) {
var ad = player.vastResponse.ads[0];
if (ad.inLine && ad.inLine.creatives && ad.inLine.creatives.length > 0) {
var creative = ad.inLine.creatives[0];
if (creative.linear && creative.linear.skipoffset) {
return parseTimeToSeconds(creative.linear.skipoffset);
}
}
}
// Альтернативный способ - парсинг XML
if (player && player.vastResponse && player.vastResponse.xml) {
var xmlDoc = new DOMParser().parseFromString(player.vastResponse.xml, "text/xml");
var linearElement = xmlDoc.querySelector("Linear");
if (linearElement && linearElement.getAttribute("skipoffset")) {
var skipoffset = linearElement.getAttribute("skipoffset");
console.log('Found skipoffset in XML:', skipoffset);
return parseTimeToSeconds(skipoffset);
}
}
} catch (e) {
console.log('Error parsing VAST skipoffset:', e);
}
return skipOffset; // возвращаем значение по умолчанию
}
// Функция для пропуска рекламы
window.skipAd = function() {
console.log('Skipping ad');
player.skipAd();
hideSkipElements();
};
// Функция для показа кнопки пропуска
function showSkipButton() {
console.log('Showing skip button');
skipButton.classList.add('visible');
skipTimer.classList.remove('visible');
if (skipTimerInterval) {
clearInterval(skipTimerInterval);
skipTimerInterval = null;
}
}
// Функция для показа таймера пропуска
function showSkipTimer() {
console.log('Showing skip timer with offset:', skipOffsetFromVast);
skipTimer.classList.add('visible');
skipButton.classList.remove('visible');
var timeLeft = skipOffsetFromVast;
skipTimeSpan.textContent = timeLeft;
skipTimerInterval = setInterval(function() {
timeLeft--;
skipTimeSpan.textContent = timeLeft;
if (timeLeft <= 0) {
showSkipButton();
}
}, 1000);
}
// Функция для скрытия элементов пропуска
function hideSkipElements() {
console.log('Hiding skip elements');
skipButton.classList.remove('visible');
skipTimer.classList.remove('visible');
if (skipTimerInterval) {
clearInterval(skipTimerInterval);
skipTimerInterval = null;
}
}
// Функция для загрузки рекламы с URL
window.loadVastAd = function(vastUrl) {
console.log('Loading VAST ad from URL:', vastUrl);
container.innerHTML = '<div class="loading">Загрузка рекламы...</div>';
hideSkipElements(); // Скрываем элементы пропуска при загрузке
// Восстанавливаем элементы пропуска
container.innerHTML += '<button id="skipButton" class="skip-button" onclick="skipAd()">Пропустить рекламу</button>';
container.innerHTML += '<div id="skipTimer" class="skip-timer">Пропустить через: <span id="skipTime">5</span>с</div>';
// Обновляем ссылки на элементы
skipButton = document.getElementById('skipButton');
skipTimer = document.getElementById('skipTimer');
skipTimeSpan = document.getElementById('skipTime');
console.log('Skip elements restored:', {
skipButton: skipButton,
skipTimer: skipTimer,
skipTimeSpan: skipTimeSpan
});
player.load(vastUrl).then(function() {
console.log('VAST ad loaded successfully');
sendToFlutter('onAdLoaded');
return player.startAd();
}).catch(function(reason) {
console.error('Failed to load ad:', reason);
container.innerHTML = '<div class="error">Ошибка загрузки рекламы: ' + reason.message + '</div>';
sendToFlutter('onAdError', reason);
});
};
// Функция для загрузки пользовательского XML
window.loadCustomXml = function(xmlContent) {
console.log('Loading custom XML ad, content length:', xmlContent.length);
container.innerHTML = '<div class="loading">Загрузка пользовательской рекламы...</div>';
hideSkipElements(); // Скрываем элементы пропуска при загрузке
// Восстанавливаем элементы пропуска
container.innerHTML += '<button id="skipButton" class="skip-button" onclick="skipAd()">Пропустить рекламу</button>';
container.innerHTML += '<div id="skipTimer" class="skip-timer">Пропустить через: <span id="skipTime">5</span>с</div>';
// Обновляем ссылки на элементы
skipButton = document.getElementById('skipButton');
skipTimer = document.getElementById('skipTimer');
skipTimeSpan = document.getElementById('skipTime');
console.log('Skip elements restored for custom XML:', {
skipButton: skipButton,
skipTimer: skipTimer,
skipTimeSpan: skipTimeSpan
});
try {
// Создаем Blob URL для пользовательского XML
var blob = new Blob([xmlContent], {type: 'application/xml'});
var url = URL.createObjectURL(blob);
console.log('Custom XML blob URL created:', url);
player.load(url).then(function() {
console.log('Custom XML ad loaded successfully');
sendToFlutter('onAdLoaded');
return player.startAd();
}).catch(function(reason) {
console.error('Failed to load custom ad:', reason);
container.innerHTML = '<div class="error">Ошибка загрузки пользовательской рекламы: ' + reason.message + '</div>';
sendToFlutter('onAdError', reason);
});
} catch (error) {
console.error('Error creating blob URL for custom XML:', error);
container.innerHTML = '<div class="error">Ошибка создания пользовательской рекламы: ' + error.message + '</div>';
sendToFlutter('onAdError', error);
}
};
// Функция для остановки рекламы
window.stopAd = function() {
console.log('Stopping ad');
player.stopAd();
};
// Функция для паузы/возобновления рекламы
window.toggleAdPlayback = function() {
if (player.isPlaying()) {
player.pauseAd();
} else {
player.resumeAd();
}
};
// Обработчики всех событий
[
'AdLoaded',
'AdStarted',
'AdStopped',
'AdSkipped',
'AdSkippableStateChange',
'AdSizeChange',
'AdLinearChange',
'AdDurationChange',
'AdExpandedChange',
'AdRemainingTimeChange',
'AdVolumeChange',
'AdImpression',
'AdVideoStart',
'AdVideoFirstQuartile',
'AdVideoMidpoint',
'AdVideoThirdQuartile',
'AdVideoComplete',
'AdClickThru',
'AdInteraction',
'AdUserAcceptInvitation',
'AdUserMinimize',
'AdUserClose',
'AdPaused',
'AdPlaying',
'AdLog',
'AdError'
].forEach(function(type) {
player.on(type, function() {
var args = Array.prototype.slice.call(arguments);
console.log('EVENT: ' + type, args);
// Отправляем событие в Flutter
var eventName = 'on' + type;
sendToFlutter(eventName, args.length > 0 ? args[0] : null);
// Специальная обработка для завершения рекламы
if (type === 'AdStopped') {
sendToFlutter('onAdComplete');
hideSkipElements();
}
// Специальная обработка для пропуска рекламы
if (type === 'AdSkipped') {
sendToFlutter('onAdSkipped');
hideSkipElements();
}
// Специальная обработка для изменения состояния пропуска
if (type === 'AdSkippableStateChange') {
if (args.length > 0 && args[0]) {
// Получаем skipoffset из VAST данных
skipOffsetFromVast = getSkipOffsetFromVast();
console.log('Ad is skippable, skip offset from VAST:', skipOffsetFromVast);
showSkipTimer(); // Показываем таймер, если реклама стала пропускаемой
} else {
hideSkipElements(); // Скрываем, если реклама не пропускаемая
}
}
// Специальная обработка для начала рекламы
if (type === 'AdStarted') {
sendToFlutter('onAdStarted');
// Проверяем, пропускаемая ли реклама
if (player.isSkippable()) {
skipOffsetFromVast = getSkipOffsetFromVast();
console.log('Ad started and is skippable, skip offset:', skipOffsetFromVast);
showSkipTimer();
}
}
// Специальная обработка для загрузки рекламы
if (type === 'AdLoaded') {
sendToFlutter('onAdLoaded');
// Проверяем skipoffset сразу после загрузки
setTimeout(function() {
if (player.isSkippable()) {
skipOffsetFromVast = getSkipOffsetFromVast();
console.log('Ad loaded and is skippable, skip offset:', skipOffsetFromVast);
}
}, 100);
}
// Специальная обработка для кликов
if (type === 'AdClickThru') {
sendToFlutter('onAdClick');
// Пытаемся открыть ссылку
if (args.length > 0 && args[0]) {
console.log('Opening click URL:', args[0]);
try {
window.open(args[0], '_blank');
} catch (e) {
console.error('Error opening click URL:', e);
}
}
}
});
});
// Загружаем рекламу по умолчанию
loadVastAd('https://platform-staging.reelcontent.com/api/public/vast/2.0/tag?campaign=cam-e951792a909f17');
}(window.VASTPlayer));
</script>
</body>
</html>