本文详解如何使用原生 css 动画 + javascript(或轻量库)实现类似 soto.shinfuji.co.jp 的平滑左→右背景滑动过渡,并叠加视差式缩放淡出效果,无需依赖重型框架。
要复现 soto.shinfuji.co.jp 那种极具沉浸感的背景轮播——即当前图从满屏略缩放+淡入,上一张图向左平滑滑出并同步缩小淡出——关键不在于更换 Slider 库,而在于精准控制 transform、scale、opacity 的组合动画时序。Slick Slider 本身完全支持该效果,但需深度定制 beforeChange 和 afterChange 回调 + 自定义 CSS 过渡类,而非仅靠 cssEase。
以下是一个轻量、高性能、无额外依赖的实现方案(兼容现代浏览器):
/* CSS */
.bg-slider {
position: relative;
width: 100vw;
height: 100vh;
overflow: hidden;
}
.slide {
position: absolute;
top: 0; left: 0;
width: 100%; height: 100%;
background-size: cover;
background-position: center;
opacity: 0;
transform: translateX(100vw) scale(1.05);
transition: transform 1.2s cubic-bezier(0.6, -0.28, 0.735, 0.045),
opacity 1.2s ease-out,
scale 1.2s cubic-bezier(0.6, -0.28, 0.735, 0.045);
}
.slide.active {
opacity: 1;
transform: translateX(0) scale(1);
}
/* 可选:添加 subtle parallax on scroll */
.slide::before {
content: '';
position: absolute;
top: 0; left: 0;
width: 100%; height: 100%;
background: inherit;
background-size: cover;
z-index: -1;
transform: scale(1.1); /* subtle zoom layer */
}// JS 控制逻辑(自动轮播 + 手动切换)
const slider = document.getElementById('bgSlider');
const slides = Array.from(slider.querySelectorAll('.slide'));
let currentIndex = 0;
let isTransitioning = false;
function goToSlide(index) {
if (isTransitioning || index === currentIndex) return;
isTransitioning = true;
// 移除 active 类
slides.forEach(s => s.classList.remove('active'));
// 设置新 slide 为 active
slides[index].classList.add('active');
// 重置其他 slide 初始状态(右侧待入场)
slides.forEach((s, i) => {
if (i !== index) {
s.style.transform = 'translateX(100vw) scale(1.05)';
s.style.opacity = '0';
}
});
// 触发重排,确保 transition
生效
void slider.offsetWidth;
// 恢复状态
setTimeout(() => {
isTransitioning = false;
}, 1200);
}
// 自动轮播
setInterval(() => {
currentIndex = (currentIndex + 1) % slides.length;
goToSlide(currentIndex);
}, 5000);
// 手动导航示例(可扩展为按钮/键盘)
document.addEventListener('keydown', e => {
if (e.key === 'ArrowRight') {
currentIndex = (currentIndex + 1) % slides.length;
goToSlide(currentIndex);
} else if (e.key === 'ArrowLeft') {
currentIndex = (currentIndex - 1 + slides.length) % slides.length;
goToSlide(currentIndex);
}
});✅ 总结:真正流畅的“缩放+滑动”背景轮播,本质是多层 DOM + 精确时序的 CSS 过渡,而非库功能堆砌。上述方案体积