情人節到了,給大家分享一個仿摩天輪效果的相冊頁面,效果如下圖:

頁面主要部分是圖檔清單,使用div包裹:
<div class="carousel-item">
<div class="carousel-box">
<div class="title">北京</div>
<div class="num">01</div>
<img src="aaa.jpg"
/>
</div>
</div>
<div class="carousel-item">
<div class="carousel-box">
<div class="title">上海</div>
<div class="num">02</div>
<img src="bbb.jpg" />
</div>
</div>
......
然後通過樣式設定圖檔位置、z-index、透明度、傾斜角度:
.carousel-item {
--items: 10;
--width: clamp(150px, 30vw, 300px);
--height: clamp(200px, 40vw, 400px);
--x: calc(var(--active) * 800%);
--y: calc(var(--active) * 200%);
--rot: calc(var(--active) * 120deg);
--opacity: calc(var(--zIndex) / var(--items) * 3 - 2);
overflow: hidden;
position: absolute;
z-index: var(--zIndex);
width: var(--width);
height: var(--height);
margin: calc(var(--height) * -0.5) 0 0 calc(var(--width) * -0.5);
border-radius: 10px;
top: 50%;
left: 50%;
user-select: none;
transform-origin: 0% 100%;
box-shadow: 0 10px 50px 10px rgba(0, 0, 0, .5);
background: black;
pointer-events: all;
transform: translate(var(--x), var(--y)) rotate(var(--rot));
transition: transform .8s cubic-bezier(0, 0.02, 0, 1);
}
其中 --active 表示圖檔相對于正在頂層的圖檔比較的內插補點比例,比如目前展示第5張圖檔,則第四張圖檔的 --active = (4-5) / (總圖檔數量 --items=10)。--zIndex表示圖檔的z-index。
樣式設定好後,再給圖檔和頁面都加上監聽事件,點選事件時點選圖檔則将該圖檔展示到最上層,滾動事件則向前向後按順序展示圖檔。
const $items = document.querySelectorAll('.carousel-item');
$items.forEach((item, i) => {
item.addEventListener('click', () => {
progress = (i / $items.length) * 100 + 10;
animate();
})
});
document.addEventListener('mousewheel', handleWheel);
document.addEventListener('mousedown', handleMouseDown);
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mouseup', handleMouseUp);
document.addEventListener('touchstart', handleMouseDown);
document.addEventListener('touchmove', handleMouseMove);
document.addEventListener('touchend', handleMouseDown);
主要的方法是通過事件擷取目标圖檔的index,再修改全部圖檔樣式的 --active和 --zIndex 值進而實作動畫效果:
const animate = () => {
progress = Math.max(0, Math.min(progress, 100));
active = Math.floor(progress / 100 * ($items.length - 1));
$items.forEach((item, index) => displayItems(item, index, active));
};
const displayItems = (item, index, active) => {
const zIndex = getZindex([...$items], active)[index];
item.style.setProperty('--zIndex', zIndex);
item.style.setProperty('--active', (index - active) / $items.length);
};
const getZindex = (array, index) => (array.map((_, i) => (index === i) ? array.length : array.length - Math.abs(index - i)));
頁面代碼下載下傳:https://download.csdn.net/download/evanyanglibo/87450156