# HTML+CSS+JS 实现轮播时间轴
# 实现效果
# CSS 部分
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>轮播时间轴</title> | |
<link rel="stylesheet" href="https://static.fontawesome.com/css/fontawesome-app.css"> | |
<!-- 引入字体图标 --> | |
<link rel="stylesheet" href="./font/iconfont.css"> | |
<!-- 引入字体 --> | |
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400&display=swap"> | |
<style> | |
* { | |
padding: 0; | |
margin: 0; | |
font-family: "Source Sans Pro", sans-serif; | |
} | |
/* 设置 html 和 body 元素为 flex 布局,水平和垂直居中对齐,高度为 100vh,背景图大小为 cover,溢出隐藏,背景图过渡动画时间为 0.7 秒 */ | |
html, | |
body { | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
height: 100vh; | |
background-size: cover; | |
overflow: hidden; | |
transition: background-image .7s ease-in-out; | |
} | |
/* 设置.shell 元素为相对定位,flex 布局,水平和垂直居中对齐,宽度和高度为 100%,盒模型为 border-box,背景颜色为 rgba (99, 99, 99, 0.8) */ | |
.shell { | |
position: relative; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
width: 100%; | |
height: 100%; | |
box-sizing: border-box; | |
background: rgba(99, 99, 99, 0.8); | |
} | |
/* 设置.button 元素为 flex 布局,两端对齐,宽度为 380px,绝对定位,左侧偏移量为 50%,水平居中,底部偏移量为 - 80px */ | |
.button { | |
display: flex; | |
justify-content: space-between; | |
align-items: center; | |
width: 380px; | |
position: absolute; | |
left: 50%; | |
transform: translateX(-50%); | |
bottom: -80px; | |
} | |
/* 设置.prev 和.next 元素过渡动画时间为 0.25 秒,层级为 99999,底部偏移量为 5px */ | |
.prev, | |
.next { | |
transition: transform 0.25s ease; | |
z-index: 99999; | |
bottom: 5px; | |
} | |
/* 设置.prev 和.next 元素中的 i 元素字体大小为 90px,颜色为 #fff,光标为指针,文字阴影为 0 0 10px #ffffff */ | |
.prev i, | |
.next i { | |
font-size: 90px; | |
color: #fff; | |
cursor: pointer; | |
text-shadow: 0 0 10px #ffffff; | |
} | |
/* 设置.shell_body 元素宽度为 100%,缩放为 0.8 倍,上内边距为 20px,下内边距为 150px */ | |
.shell_body { | |
width: 100%; | |
transform: scale(.8); | |
padding: 20px 0 150px 0; | |
} | |
/* 设置.shell_slider 元素为相对定位,过渡动画时间为 1 秒,背景为透明 */ | |
.shell_slider { | |
position: relative; | |
transition: transform 1s ease-in-out; | |
background: transparent; | |
} | |
/* 设置.item 元素为相对定位,左浮动,左右外边距为 20px */ | |
.item { | |
position: relative; | |
float: left; | |
margin: 0 20px; | |
} | |
/* 设置.frame 元素为相对定位,宽度和高度为 100%,过渡动画时间为 1 秒,3D 变换模式为保留 3D 效果 */ | |
.frame { | |
position: relative; | |
width: 100%; | |
height: 100%; | |
transition: transform 1s ease-in-out; | |
transform-style: preserve-3d; | |
} | |
/* 设置.frame 元素的伪元素为绝对定位,底部偏移量为 - 16%,宽度为 100%,高度为 60px,背景颜色为 #ffffff1c,盒阴影为 0px 0px 15px 5px #ffffff1c,3D 变换为绕 X 轴旋转 90 度并向上平移 20px */ | |
.frame:after { | |
content: ""; | |
position: absolute; | |
bottom: -16%; | |
width: 100%; | |
height: 60px; | |
background: #ffffff1c; | |
box-shadow: 0px 0px 15px 5px #ffffff1c; | |
transform: rotateX(90deg) translate3d(0px, -20px, 0px); | |
} | |
/* 设置.box 元素为 flex 布局,纵向排列,水平和垂直居中对齐,绝对定位,宽度和高度为 100%,边框为 4px 实心白色,透视效果为 1000px,3D 变换模式为保留 3D 效果 */ | |
.box { | |
display: flex; | |
flex-direction: column; | |
justify-content: center; | |
align-items: center; | |
position: absolute; | |
width: 100%; | |
height: 100%; | |
border: 4px solid #fff; | |
perspective: 1000px; | |
transform-style: preserve-3d; | |
} | |
/* 设置.box 元素中的 h1 和 span 元素颜色为 #fff,Z 轴平移距离为 20px */ | |
.box h1, | |
.box span { | |
color: #fff; | |
transform: translateZ(20px); | |
} | |
/* 设置.box 元素中的 h1 元素文字阴影为 0 0 30px #1f05b4,字体大小为 100px */ | |
.box h1 { | |
text-shadow: 0 0 30px #1f05b4; | |
font-size: 100px; | |
} | |
/* 设置.box 元素中的 span 元素为绝对定位,底部偏移量为 20px,左右内边距为 25px,文字阴影为 0 0 10px #1f05b4 */ | |
.box span { | |
position: absolute; | |
bottom: 20px; | |
padding: 0 25px; | |
text-shadow: 0 0 10px #1f05b4; | |
} | |
/* 设置.front、.left 和.right 元素的盒阴影为 0 0 50px #ffffff,背景图大小为 cover */ | |
.front, | |
.left, | |
.right { | |
box-shadow: 0 0 50px #ffffff; | |
background-size: cover; | |
} | |
/* 设置.left 和.right 元素的顶部偏移量为 0,宽度为 60px,背面不可见 */ | |
.right, | |
.left { | |
top: 0; | |
width: 60px; | |
backface-visibility: hidden; | |
} | |
/* 设置.left 元素的左侧偏移量为 0,左边框宽度为 5px,3D 变换为向右平移 1px,Z 轴平移 - 60px,绕 Y 轴逆时针旋转 90 度,变换原点为左侧 */ | |
.left { | |
left: 0; | |
border-left-width: 5px; | |
transform: translate3d(1px, 0, -60px) rotateY(-90deg); | |
transform-origin: 0%; | |
} | |
/* 设置.right 元素的右侧偏移量为 0,右边框宽度为 5px,3D 变换为向左平移 1px,Z 轴平移 - 60px,绕 Y 轴顺时针旋转 90 度,变换原点为右侧 */ | |
.right { | |
right: 0; | |
border-right-width: 5px; | |
transform: translate3d(-1px, 0, -60px) rotateY(90deg); | |
transform-origin: 100%; | |
} | |
</style> | |
</head> |
# HTML 部分
<body> | |
<div class="shell"> | |
<div class="shell_body"> | |
<div class="button"> | |
<div class="prev"><i class="iconfont icon-backward_filled"></i></div> | |
<div class="next"><i class="iconfont icon-forward_filled"></i></div> | |
</div> | |
<div class="shell_slider"> | |
<div class="item"> | |
<div class="frame"> | |
<div class="box front"> | |
<h1>2014</h1> | |
<span>-In the year 2014 I reached the age of 13-</span> | |
</div> | |
<div class="box left"></div> | |
<div class="box right"> </div> | |
</div> | |
</div> | |
<div class="item"> | |
<div class="frame"> | |
<div class="box front"> | |
<h1>2015</h1> | |
<span>-In the year 2015 I reached the age of 14-</span> | |
</div> | |
<div class="box left"></div> | |
<div class="box right"> </div> | |
</div> | |
</div> | |
<div class="item"> | |
<div class="frame"> | |
<div class="box front"> | |
<h1>2016</h1> | |
<span>-In the year 2016 I reached the age of 15-</span> | |
</div> | |
<div class="box left"></div> | |
<div class="box right"></div> | |
</div> | |
</div> | |
<div class="item"> | |
<div class="frame"> | |
<div class="box front"> | |
<h1>2017</h1> | |
<span>-In the year 2017 I reached the age of 16-</span> | |
</div> | |
<div class="box left"></div> | |
<div class="box right"> </div> | |
</div> | |
</div> | |
<div class="item"> | |
<div class="frame"> | |
<div class="box front"> | |
<h1>2018</h1> | |
<span>-In the year 2018 I reached the age of 17-</span> | |
</div> | |
<div class="box left"></div> | |
<div class="box right"> </div> | |
</div> | |
</div> | |
<div class="item"> | |
<div class="frame"> | |
<div class="box front"> | |
<h1>2019</h1> | |
<span>-In the year 2019 I reached the age of 18-</span> | |
</div> | |
<div class="box left"></div> | |
<div class="box right"> </div> | |
</div> | |
</div> | |
<div class="item"> | |
<div class="frame"> | |
<div class="box front"> | |
<h1>2020</h1> | |
<span>-In the year 2020 I reached the age of 18-</span> | |
</div> | |
<div class="box left"></div> | |
<div class="box right"> </div> | |
</div> | |
</div> | |
<div class="item"> | |
<div class="frame"> | |
<div class="box front"> | |
<h1>2021</h1> | |
<span>-In the year 2021 I reached the age of 19-</span> | |
</div> | |
<div class="box left"></div> | |
<div class="box right"> </div> | |
</div> | |
</div> | |
<div class="item"> | |
<div class="frame"> | |
<div class="box front"> | |
<h1>2022</h1> | |
<span>-In the year 2022 I reached the age of 20-</span> | |
</div> | |
<div class="box left"></div> | |
<div class="box right"> </div> | |
</div> | |
</div> | |
<div class="item"> | |
<div class="frame"> | |
<div class="box front"> | |
<h1>2023</h1> | |
<span>-In the year 2023 I reached the age of 21-</span> | |
</div> | |
<div class="box left"></div> | |
<div class="box right"> </div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</body> |
# JS 部分
<script> | |
// 这段 JavaScript 代码的作用是实现一个图片轮播效果。首先,通过 document.getElementsByClassName ('item') 获取到所有具有 item 类名的元素,并将它们存储在 items 变量中。 | |
// 然后,通过一个循环遍历每个 item 元素。在循环中,首先获取当前的 item 元素,然后通过 getElementsByClassName 方法获取到该 item 下的 frame、front、left 和 right 元素,并将它们分别存储在 frame、frontBox、leftBox 和 rightBox 变量中。 | |
// 接下来,通过设置 frontBox、leftBox 和 rightBox 的 style.backgroundImage 属性,将背景图片设置为 'url (./img/' + (i + 1).toString ().padStart (2, '0') + '.jpg)',其中 (i + 1).toString ().padStart (2, '0') 表示将循环变量 i 加 1 后转换为字符串,并在前面补 0,以保证图片的文件名格式正确。 | |
// 接着,定义了一个立即执行函数,并在函数内部进行了一些操作。首先,通过 document.getElementsByClassName ('shell')[0] 获取到具有 shell 类名的元素,并将其存储在 shell 变量中。然后,通过 shell.getElementsByClassName 方法获取到该 shell 元素下的 shell_slider、item、prev 和 next 元素,并将它们分别存储在 slider、items、prevBtn 和 nextBtn 变量中。 | |
// 接下来,定义了一些变量,包括 width、height、totalWidth、margin、currIndex、interval 和 intervalTime。width 和 height 分别表示每个 item 的宽度和高度,totalWidth 表示所有 item 的总宽度,margin 表示 item 的外边距,currIndex 表示当前显示的 item 的索引,interval 表示定时器的 ID,intervalTime 表示定时器的时间间隔。 | |
// 然后,定义了 init 函数,该函数用于初始化一些操作。在该函数中,首先调用 resize 函数调整大小,然后调用 move 函数将显示的 item 移动到中间位置,接着调用 bindEvents 函数绑定事件,最后调用 timer 函数启动定时器。 | |
// 接着,定义了 resize 函数,该函数用于在窗口大小变化时调整大小。在该函数中,首先计算出新的 width 和 height,然后根据计算结果设置 slider 的宽度,以及每个 item 的宽度和高度。 | |
// 接下来,定义了 bindEvents 函数,该函数用于绑定事件。在该函数中,首先绑定了窗口大小变化时调用 resize 函数的事件,然后绑定了点击 prev 按钮和 next 按钮时调用 prev 函数和 next 函数的事件。 | |
// 最后,在立即执行函数的末尾,调用了 init 函数来初始化页面,并定义了 move、timer、prev 和 next 函数。其中,move 函数用于移动 shell 到指定的 item,timer 函数用于启动定时器,prev 函数用于切换到上一个 item,next 函数用于切换到下一个 item。 | |
// 获取所有的 item 元素 | |
var items = document.getElementsByClassName('item'); | |
// 循环遍历每个 item | |
for (var i = 0; i < items.length; i++) { | |
// 获取当前 item | |
var item = items[i]; | |
var frame = item.getElementsByClassName('frame')[0]; | |
var frontBox = frame.getElementsByClassName('front')[0]; | |
var leftBox = frame.getElementsByClassName('left')[0]; | |
var rightBox = frame.getElementsByClassName('right')[0]; | |
// 设置背景图片 | |
frontBox.style.backgroundImage = 'url(./img/' + (i + 1).toString().padStart(2, '0') + '.jpg)'; | |
leftBox.style.backgroundImage = 'url(./img/' + (i + 1).toString().padStart(2, '0') + '.jpg)'; | |
rightBox.style.backgroundImage = 'url(./img/' + (i + 1).toString().padStart(2, '0') + '.jpg)'; | |
} | |
(function () { | |
"use strict"; | |
var shell = document.getElementsByClassName('shell')[0]; | |
var slider = shell.getElementsByClassName('shell_slider')[0]; | |
var items = shell.getElementsByClassName('item'); | |
var prevBtn = shell.getElementsByClassName('prev')[0]; | |
var nextBtn = shell.getElementsByClassName('next')[0]; | |
// 定义变量 | |
var width, height, totalWidth, margin = 20, | |
currIndex = 0, | |
interval, intervalTime = 3000; | |
function init() { | |
// 初始化函数 | |
resize(); | |
move(Math.floor(items.length / 2)); | |
bindEvents(); | |
timer(); | |
} | |
function resize() { | |
// 窗口大小变化时调整大小 | |
width = Math.max(window.innerWidth * .20, 275); | |
height = window.innerHeight * .5; | |
totalWidth = width * items.length; | |
// 设置 slider 宽度 | |
slider.style.width = totalWidth + "px"; | |
// 设置每个 item 的宽度和高度 | |
for (var i = 0; i < items.length; i++) { | |
let item = items[i]; | |
item.style.width = (width - (margin * 2)) + "px"; | |
item.style.height = height + "px"; | |
} | |
} | |
function bindEvents() { | |
// 窗口大小变化时调整大小 | |
window.onresize = resize; | |
// 点击 prev 按钮切换 item | |
prevBtn.addEventListener('click', () => { prev(); }); | |
nextBtn.addEventListener('click', () => { next(); }); | |
} | |
init(); | |
function move(index) { | |
// 移动 shell 到指定的 item | |
if (index < 1) index = items.length; | |
if (index > items.length) index = 1; | |
currIndex = index; | |
// 遍历所有 item | |
for (var i = 0; i < items.length; i++) { | |
let item = items[i], | |
box = item.getElementsByClassName('frame')[0]; | |
if (i == (index - 1)) { | |
// 当前 item 添加 active 类并设置 3D 效果 | |
item.classList.add('item--active'); | |
box.style.transform = "perspective(1200px)"; | |
} else { | |
// 其他 item 移除 active 类并设置 3D 效果 | |
item.classList.remove('item--active'); | |
box.style.transform = "perspective(1200px) rotateY(" + (i < (index - 1) ? 40 : -40) + "deg)"; | |
} | |
} | |
// 移动 slider | |
slider.style.transform = "translate3d(" + ((index * -width) + (width / 2) + window.innerWidth / 2) + "px, 0, 0)"; | |
// 设置 body 背景图片 | |
var frontBox = items[index - 1].getElementsByClassName('front')[0]; | |
document.body.style.backgroundImage = frontBox.style.backgroundImage; | |
} | |
function timer() { | |
// 定时器,自动切换 shell | |
clearInterval(interval); | |
interval = setInterval(() => { | |
move(++currIndex); | |
}, intervalTime); | |
} | |
// 切换 item | |
function prev() { | |
move(--currIndex); | |
timer(); | |
} | |
function next() { | |
move(++currIndex); | |
timer(); | |
} | |
})(); | |
</script> |
在 VScode 中新建.html 文件将以上代码段依次粘贴进去就完成了!不要忘记把 img 文件夹放在同级根目录下,使用到的图片都要以 01.jpg,02.jpg……10.jpg 形式命名哦,图片分辨率建议 1200*560px~