仿写京东首页轮播图
上学期期末的时候web应用设计课有一个作业是要求仿写京东首页轮播图,感觉完成得还原度还算挺高,一直想写下博客记录一下,也是因为实习和项目在忙一直拖了很久没有写,今天补一下。
效果要求
先看一下要我们仿写的页面 京东(JD.COM)-正品低价、品质保障、配送及时、轻松购物!
可以看到我们要实现功能:
- 自动轮播
- 鼠标悬浮在图片上停止自动轮播
- 点击左右侧按钮切换轮播图片
- 底部选项按钮随着页面切换而变化,同时鼠标浮入指定按钮会显示相应图片
实现
页面结构分析
主要还是F12一顿抄,让我们看一下dom结构以及使用的布局:
dom结构
就是把轮播图列表放在两个左右控制的按钮之间,最底部为圆点按钮列表。
因此我们的页面的页面结构也跟他相同
html
<body>
<div class="container">
<button class="slider_control_left">
<li class="iconfont icon-jiantou_liebiaoxiangzuo"></li>
</button>
<div class="img_list">
<ul>
<li><img src="./images/1.png" alt=""></li>
<li><img src="./images/2.jpg" alt=""></li>
<li><img src="./images/3.jpg" alt=""></li>
<li><img src="./images/4.jpg" alt=""></li>
<li><img src="./images/5.jpg" alt=""></li>
<li><img src="./images/6.jpg" alt=""></li>
</ul>
</div>
<button class="slider_control_right">
<li class="iconfont icon-jiantou_liebiaoxiangyou"></li>
</button>
<div class="dot_list">
<ul>
<li class="indicators"></li>
<li class="indicators"></li>
<li class="indicators"></li>
<li class="indicators"></li>
<li class="indicators"></li>
<li class="indicators"></li>
</ul>
</div>
</div>
</body>
布局
dom结构不是最重要的,最重要的是布局
F12参考一下它是怎么实现的 我们从外到里进行分析:
- 图片列表容器与最外层容器大小相同,占满
- 左右两个按钮使用绝对定位,根据最外层容器定位在最外层容器的左右两边,上下居中
- 圆点按钮列表容器使用绝对定位,根据最外层容器定位在最外层容器的底部
- 轮播图列表使用绝对定位,根据最外层容器定位,由于绝对定位会脱离文档流,因此图片列表在z轴上叠加,根据标签的顺序,最后一个标签的z-index值最大,因此的图片为6.jpg,并且把图片设置为透明
- 圆点列表使用inline-block布局,使得圆点横向排列
切换效果的实现
继续F12,可以看出,样式改变的实现方法就是在鼠标点击或鼠标浮动在元素上面时,为元素添加样式,由于css的叠加属性覆盖原有样式,显示新的样式,实现样式切换。而轮播效果的实现就是修改轮播图片的层级,使得其在最上层。
改变的样式:
- 修改圆点的样式
- 轮播的实现方法:需要轮播的图片,z-index设置为1,透明度设置为1
css完整代码如下:
css
*{
margin: 0;
padding: 0;
}
.container,.img_list{
margin: 0 auto;
background-color: rgb(252, 255, 255);
width: 590px;
height: 470px;
position: relative;
}
button{
position: absolute;
border: none;
background-color: rgba(0,0,0,.15);
width: 25px;
height: 35px;
top: 50%;
z-index: 2;
cursor: pointer;
}
button:hover{
background-color: rgba(0,0,0,.5);
}
button li{
color: white;
font-weight:bold;
}
.slider_control_left{
left: 0;
border-top-right-radius: 18px;
border-bottom-right-radius: 18px;
}
.slider_control_right{
right: 0;
border-top-left-radius: 18px;
border-bottom-left-radius: 18px;
}
.img_list ul li{
position: absolute;
width: 100%;
height: 100%;
}
ul li img{
display: block;
position: relative;
width: 590px;
height: 470px;
opacity: 0;
transition: opacity 300ms ease-in-out 0s;
}
.dot_list ul{
position: absolute;
bottom: 20px;
left:30px;
z-index: 2;
}
.indicators{
display: inline-block;
width: 8px;
height: 8px;
background-color: rgba(255,255,255,.4);
border-radius: 50%;
border: 1px solid rgb(255, 255,255,.4);
margin-right: 4px;
cursor: pointer;
transition: opacity 300ms ease-in-out 0s;
}
.indicators_active{
top:2px ;
width: 9px ;
height: 9px ;
margin-right: 4px;
border: 3px solid rgba(0,0,0,.1);
background-color: white;
}
.img_active{
z-index: 1;
opacity: 1;
}
javascript
实现思路
我们获取到的是图片数组和圆点按钮数组,只要确定数组下标,添加对应下标的数组元素的样式,就可以实现轮播效果。然后,在按钮上设置事件监听器,对于左右切换按钮,点击后,数组下标-1或+1,对于圆点按钮,圆点按钮的数组下标与轮播图片的数组下标相同,下面的代码注释写得很清楚,细看一下
js完整代码
js
{/* <script defer></script> */}
/* ---------------------------------- 全局变量 ---------------------------------- */
const imgList = document.getElementsByTagName("img");
const dot_list = document.querySelectorAll(".dot_list>ul>li");
const rightBtn = document.getElementsByClassName("slider_control_right")[0];
const leftBtn = document.getElementsByClassName("slider_control_left")[0];
const container = document.getElementsByClassName("container")[0];
const length = imgList.length;
let currentImgId =0;//当前图片下标
let timer = null;
/* -------------------------------------------------------------------------- */
/* 原始操作 */
/* -------------------------------------------------------------------------- */
/* --------------------------------- 页面和点跳转 --------------------------------- */
const pageTurn = ()=>{
imgList[currentImgId].classList.add("img_active");
dot_list[currentImgId].classList.add("indicators_active")
}
/* --------------------------------- 清除其余页面 --------------------------------- */
const clearPage = ()=>{
imgList[currentImgId].classList.remove("img_active");
dot_list[currentImgId].classList.remove("indicators_active")
}
/* ---------------------------------- 状态初始化 --------------------------------- */
const initState = ()=>{
imgList[0].classList.add("img_active");
dot_list[0].classList.add("indicators_active");
currentImgId = 0;
}
/* ---------------------------------- 设置定时器 --------------------------------- */
const setAutoTurn = () =>{
timer = setInterval(()=>{
rightBtn.click();
},2000)
}
/* ---------------------------------- 清除定时器 --------------------------------- */
const clearAutoTurn = ()=>{
clearInterval(timer);
}
/* -------------------------------------------------------------------------- */
/* 功能 */
/* -------------------------------------------------------------------------- */
/* --------------------------------- 左右切换按钮 --------------------------------- */
const click_to_pageTurn = ()=>{
leftBtn.addEventListener("click",()=>{
clearPage();
if(currentImgId === 0){
currentImgId = length;
}
currentImgId = currentImgId -1;
pageTurn();
})
rightBtn.addEventListener("click",()=>{
clearPage();
currentImgId = (currentImgId+1) % length;
pageTurn();
})
}
/* -------------------------------- 底部按钮浮入切换 -------------------------------- */
const mouseover_to_pageTurn = ()=>{
for(let i=0; i<length; i++ ){
dot_list[i].addEventListener("mouseover",()=>{
clearPage();
currentImgId = i;
pageTurn();
})
}
}
/* ---------------------------------- 定时轮播 ---------------------------------- */
const autoTurn = () => {
setAutoTurn();
container.onmouseenter = ()=>{
clearAutoTurn();
}
container.onmouseleave = ()=>{
setAutoTurn();
}
}
/* -------------------------------------------------------------------------- */
/* 启动函数 */
/* -------------------------------------------------------------------------- */
const init = ()=>{
initState();
click_to_pageTurn();
mouseover_to_pageTurn();
autoTurn();
}
/* -------------------------------------------------------------------------- */
/* 执行 */
/* -------------------------------------------------------------------------- */
init()
最终效果
完整的项目代码在我的github仓库获取
github.com/clumsy-goos...