Рабочий вариант (возможно кому-то пригодится):
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Swiper Slider with Zoom Effect</title>
<link rel="stylesheet" href="https://unpkg.com/swiper/swiper-bundle.min.css">
<style>
body {
margin: 0;
font-family: Arial, sans-serif;
}
.swiper-container {
width: 100%;
height: 100vh;
}
.swiper-slide {
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
cursor: pointer;
}
.swiper-slide img {
max-width: 100%;
height: 100%;
object-fit: cover;
transition: none;
}
/* Индикатор паузы */
.pause-indicator {
position: absolute;
top: 20px;
right: 20px;
background: rgba(0, 0, 0, 0.7);
color: white;
padding: 10px;
border-radius: 5px;
font-size: 14px;
z-index: 10;
opacity: 0;
transition: opacity 0.3s;
}
.pause-indicator.show {
opacity: 1;
}
</style>
</head>
<body>
<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swiper-slide"><img src="https://images.wallpaperscraft.com/image/single/lynx_animal_predator_1398659_1920x1080.jpg" alt=""></div>
<div class="swiper-slide"><img src="https://images.wallpaperscraft.com/image/single/lake_trees_sunset_1398065_1920x1080.jpg" alt=""></div>
<div class="swiper-slide"><img src="https://images.wallpaperscraft.com/image/single/field_river_trees_1399666_1920x1080.jpg" alt=""></div>
</div>
<div class="swiper-pagination"></div>
<div class="pause-indicator">Пауза (5 сек)</div>
</div>
<script src="https://unpkg.com/swiper/swiper-bundle.min.js"></script>
<script>
const swiper = new Swiper('.swiper-container', {
loop: true,
autoplay: {
delay: 5000,
disableOnInteraction: false,
},
pagination: {
el: '.swiper-pagination',
clickable: true,
},
});
let zoomAnimationId;
let zoomStartTime;
let zoomDuration = 5000; // 5 секунд
let isPaused = false;
let pauseTimeout;
let pausedProgress = 0; // Прогресс анимации на момент паузы
const pauseIndicator = document.querySelector('.pause-indicator');
function animateZoom(startTime, initialProgress = 0) {
const activeSlide = document.querySelector('.swiper-slide-active img');
if (!activeSlide) return;
function zoom(currentTime) {
if (!startTime) startTime = currentTime;
const elapsed = currentTime - startTime;
const totalProgress = Math.min((elapsed + initialProgress * zoomDuration) / zoomDuration, 1);
// Вычисляем масштаб от 1 до 1.2
const scale = 1 + (totalProgress * 0.2);
activeSlide.style.transform = `scale(${scale})`;
activeSlide.style.transition = 'none';
if (totalProgress < 1 && !isPaused) {
zoomAnimationId = requestAnimationFrame(zoom);
} else if (totalProgress >= 1 && !isPaused) {
// Анимация завершена, переходим к следующему слайду
activeSlide.style.transform = 'scale(1)';
activeSlide.style.transition = 'transform 0.3s ease-out';
swiper.slideNext();
}
// Сохраняем текущий прогресс
pausedProgress = totalProgress;
}
zoomAnimationId = requestAnimationFrame(zoom);
}
function startZoom() {
if (isPaused) return;
pausedProgress = 0;
zoomStartTime = performance.now();
animateZoom();
}
function pauseZoom() {
isPaused = true;
if (zoomAnimationId) {
cancelAnimationFrame(zoomAnimationId);
}
// Показываем индикатор паузы
pauseIndicator.classList.add('show');
// Автоматическое возобновление через 5 секунд
pauseTimeout = setTimeout(() => {
resumeZoom();
}, 5000);
}
function resumeZoom() {
isPaused = false;
// Скрываем индикатор паузы
pauseIndicator.classList.remove('show');
// Очищаем таймаут автовозобновления
if (pauseTimeout) {
clearTimeout(pauseTimeout);
pauseTimeout = null;
}
// Возобновляем анимацию с сохраненного прогресса
if (pausedProgress < 1) {
animateZoom(performance.now(), pausedProgress);
} else {
// Если анимация была завершена, начинаем новую
startZoom();
}
// Возобновляем autoplay
swiper.autoplay.start();
}
function togglePause() {
if (isPaused) {
resumeZoom();
} else {
// Останавливаем autoplay
swiper.autoplay.stop();
pauseZoom();
}
}
// Обработчик смены слайда
swiper.on('slideChange', () => {
// Сбрасываем состояние предыдущего слайда
document.querySelectorAll('.swiper-slide img').forEach(img => {
img.style.transform = 'scale(1)';
img.style.transition = 'transform 0.3s ease-out';
});
// Очищаем анимацию
if (zoomAnimationId) {
cancelAnimationFrame(zoomAnimationId);
}
// Если не на паузе, запускаем новую анимацию
if (!isPaused) {
setTimeout(() => {
startZoom();
}, 100); // Небольшая задержка для корректной работы
}
});
// Добавляем обработчики кликов
document.querySelectorAll('.swiper-slide').forEach(slide => {
slide.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
togglePause();
});
});
// Запускаем первую анимацию после загрузки
swiper.on('init', () => {
setTimeout(() => {
startZoom();
}, 100);
});
// Если swiper уже инициализирован
if (swiper.initialized) {
setTimeout(() => {
startZoom();
}, 100);
}
</script>
</body>
</html>