405 lines
No EOL
17 KiB
HTML
405 lines
No EOL
17 KiB
HTML
<!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> |