一、实现效果
二、思路
1、核心animate.js动画js
单独做一个动画的js,动画都是基于这个函数,用的时候调用即可,animate(obj, target, callback)
函数有三个形参,obj为动画的对象,target为目标动画移动距离,callback为动画执行完在之后的回调函数。
//动画函数
//obj 动画绑定对象 traget 目标移动距离 callback回调函数
function animate(obj, target, callback) {
clearInterval(obj.timer);
obj.timer = setInterval(function() {
//步长 = (目标值-现在位置)/10 取整
let step = (target - obj.offsetLeft) / 10;
//大于0向上取整 小于0向下取整
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
//停止动画定时器
clearInterval(obj.timer);
//判断回调函数是否存在
if (callback) {
callback();
}
}
obj.style.left = obj.offsetLeft + step + 'px';
}, 15)
}
2、菜单栏滑块效果
1、html布局:单独布局一个div盒子作为滑块
<div class="header">
<div class="nav">
<ul>
<a href="javascript:;">
<li>首页</li>
</a>
<a href="javascript:;">
<li>产品</li>
</a>
<a href="javascript:;">
<li>新闻</li>
</a>
<a href="javascript:;">
<li>服务</li>
</a>
<a href="javascript:;">
<li>帮助</li>
</a>
<a href="javascript:;">
<li>关于</li>
</a>
<a href="javascript:;">
<li>联系我们</li>
</a>
</ul>
<div class="cloud"></div>
</div>
</div>
2、滑块js
(1)鼠标移入移出调用animate
函数来执行动画,并且对应的菜单字体颜色变色
(2)鼠标点击后滑块停止在点击的菜单下面,字体变色,鼠标继续滑动会以目前点为初始点进行滑动,这里定义一个参数来接收点击的位置元素的offsetLeft
//菜单栏滑动块
let cloud = document.querySelector('.cloud');
let nav = document.querySelector('.nav');
let lis = nav.querySelectorAll('li');
let current = 0; //起始位置
for (let i = 0; i < lis.length; i++) {
lis[i].addEventListener('mouseenter', function() {
animate(cloud, this.offsetLeft);
})
lis[i].addEventListener('mouseleave', function() {
animate(cloud, current);
})
lis[i].addEventListener('click', function() {
for (let i = 0; i < lis.length; i++) {
lis[i].style.color = '';
}
lis[i].style.color = '#00BFFF'
current = this.offsetLeft;
})
}
3、Banner
banner滑动布局
1、小图标
(1)根据图片数量动态生成小图标按钮,获取图片的ul.children.length
,来动态生成li
标签
(2)鼠标移入变色,排他原则
(3)鼠标划入那个小图标,banner图片会滑动到那张,通过小图标序号i * 图片宽度
来实现banner图片的滑动效果
for (let i = 0; i < ul.children.length; i++) {
let li = this.document.createElement('li');
ol.appendChild(li);
li.setAttribute('index', i)
li.addEventListener('mouseover', function() {
for (let i = 0; i < ol.children.length; i++) {
ol.children[i].style.backgroundColor = 'white';
}
this.style.backgroundColor = '#00BFFF';
animate(ul, -imgWidth * i)
let index = this.getAttribute('index');
num = index;
circle = index;
})
}
ol.children[0].style.backgroundColor = '#00BFFF';
2、左右按钮
(1)点击左右按钮,图片滑动,定义一个参数num,滑动距离=num*图片宽度
。
(2)点击左右按钮后num++
,并且小按钮也跟随变化,定义变量circle
,要保持两者一致,去一个中间变量index
来保持num
与circle
一致,index
可以定义index
属性:li.setAttribute('index', i)
(3)防抖,当点击左右按钮过快会出现图片滑动变快,可以定义一个flag = true
来作为节流阀
首先判断flag,进入后先将flag = false
,在动画执行完之后,回调函数callback里面将flag = true
(4)banner滑动无缝衔接,当滑动到在最后一张图片时候,需要有个判断,跳到第一张,这里在最后一个li加入第一张图片的li,即可实现无缝衔接。加入最后一个li可以采用动态添加节点的方式,克隆第一个节点。
//克隆第一张图片放在最后节点上面
let firstImg = ul.children[0].cloneNode(true);
ul.appendChild(firstImg);
if (num == ul.children.length - 1) {
ul.style.left = 0; //没有动画效果,直接跳到第一张图片
num = 0;
}
// 封装右按钮函数
function arrow_right() {
if (flag) { //防抖
flag = false
if (num == ul.children.length - 1) {
ul.style.left = 0;
num = 0;
}
num++;
animate(ul, -num * imgWidth, function() {
flag = true;
})
circle++;
if (circle == ol.children.length) {
circle = 0;
}
for (let i = 0; i < ol.children.length; i++) {
ol.children[i].style.backgroundColor = 'white';
}
ol.children[circle].style.backgroundColor = '#00BFFF';
}
}
//封装左按钮函数
function arrow_left() {
if (flag) { //防抖
flag = false;
if (num == 0) {
num = ul.children.length - 1;
ul.style.left = -num * imgWidth + 'px';
}
num--;
animate(ul, -num * imgWidth, function() {
flag = true;
})
if (circle == 0) {
circle = ol.children.length;
}
circle--;
for (let i = 0; i < ol.children.length; i++) {
ol.children[i].style.backgroundColor = 'white';
}
ol.children[circle].style.backgroundColor = '#00BFFF';
}
}
3、定时播放banner
timer = setInterval(arrow_right, 2500);
4、鼠标移入停止定时器,移出开启定时器
鼠标移入左右按钮出现
bannerimg.addEventListener('mouseover', function() {
arrow_l.style.display = 'block';
arrow_r.style.display = 'block';
clearInterval(timer);
timer = null;
})
bannerimg.addEventListener('mouseout', function() {
arrow_l.style.display = 'none';
arrow_r.style.display = 'none';
timer = setInterval(arrow_right, 2500);
})
附录:
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Complexbanner</title>
<link rel="stylesheet" href="./banner.css">
<link rel="stylesheet" href="./img/font-awesome-4.7.0/css/font-awesome.min.css">
<script src="./animate.js"></script>
<script src="./banner.js"></script>
</head>
<body>
<div class="contain">
<div class="header">
<div class="nav">
<ul>
<a href="javascript:;">
<li>首页</li>
</a>
<a href="javascript:;">
<li>产品</li>
</a>
<a href="javascript:;">
<li>新闻</li>
</a>
<a href="javascript:;">
<li>服务</li>
</a>
<a href="javascript:;">
<li>帮助</li>
</a>
<a href="javascript:;">
<li>关于</li>
</a>
<a href="javascript:;">
<li>联系我们</li>
</a>
</ul>
<div class="cloud"></div>
</div>
</div>
<div class="bannerimg">
<a href="javascript:;" class="arrow-l"><i class="fa fa-chevron-left fa-2x" aria-hidden="true"></i></a>
<a href="javascript:;" class="arrow-r"><i class="fa fa-chevron-right fa-2x" aria-hidden="true"></i> </a>
<ul>
<li>
<a href="javascript:;"><img src="./img/banner1.jpg" alt=""></a>
</li>
<li>
<a href="javascript:;"><img src="./img/banner3.jpg" alt=""></a>
</li>
<li>
<a href="javascript:;"><img src="./img/banner4.jpg" alt=""></a>
</li>
</ul>
<ol class="circle">
</ol>
</div>
</body>
</html>
CSS:
* {
margin: 0 auto;
padding: 0 auto;
}
a {
text-decoration: none;
color: black;
}
.contain {
text-align: center;
margin: 0 auto;
padding: 0 auto;
}
/* header头部 */
.header {
position: fixed;
left: 0;
top: 0;
z-index: 999;
height: 50px;
width: 100%;
background-color: white;
box-shadow: 0px 2px 8px 0px rgb(0 0 0 / 15%);
}
.nav {
margin-left: 25%;
width: 1500px;
height: 50px;
line-height: 50px;
}
.header .nav ul li {
float: left;
list-style: none;
margin: 0 20px;
height: 47px;
width: 80px;
}
.header .nav ul li:hover {
color: #00BFFF;
}
.cloud {
height: 3px;
width: 80px;
background-color: #00BFFF;
/* margin-left: 28.2%; */
position: absolute;
left: 536px;
top: 47px;
}
/* benner部分 */
.bannerimg {
position: relative;
left: -40px;
top: 0;
width: 1960px;
height: 660px;
/* overflow: hidden; */
/* border: 4px solid red; */
/* z-index: 1000; */
/* padding-left: -100px; */
}
.bannerimg img {
/* margin-left: -40px; */
width: 1960px;
height: 660px;
margin: 0;
padding: 0;
}
.bannerimg ul {
width: 900%;
height: 660px;
position: absolute;
left: 0;
top: 0;
/* background-color: pink; */
margin: 0;
padding: 0;
}
.bannerimg ul li {
float: left;
list-style: none;
}
.arrow-l {
position: absolute;
left: 50px;
top: 50%;
color: rgba(255, 255, 255, .8);
display: none;
z-index: 999;
}
.arrow-l :hover {
color: white;
}
.arrow-r {
position: absolute;
right: 16px;
top: 50%;
color: rgba(255, 255, 255, .8);
display: none;
z-index: 999;
}
.arrow-r :hover {
color: white;
}
.bannerimg ol {
position: absolute;
left: 40%;
bottom: 2%;
width: 500px;
height: 40px;
z-index: 99;
}
.current {
background-color: red;
}
.circle li {
/* position: absolute;
left: 50%;
bottom: 10%; */
width: 50px;
height: 2px;
background-color: white;
cursor: pointer;
margin: 0 10px;
float: left;
list-style: none;
}
JS:
1、动画animate.js
//动画函数
//obj 动画绑定对象 traget 目标移动距离 callback回调函数
function animate(obj, target, callback) {
clearInterval(obj.timer);
obj.timer = setInterval(function() {
//步长 = (目标值-现在位置)/10 取整
let step = (target - obj.offsetLeft) / 10;
//大于0向上取整 小于0向下取整
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
//停止动画定时器
clearInterval(obj.timer);
if (callback) {
callback();
}
}
obj.style.left = obj.offsetLeft + step + 'px';
}, 15)
}
2、banner.js
window.addEventListener('load', function() {
let bannerMain = document.querySelector('.bannerMain');
let bannerimg = document.querySelector('.bannerimg');
let ul = bannerimg.querySelector('ul');
let ol = bannerimg.querySelector('ol');
arrow_l = document.querySelector('.arrow-l');
arrow_r = document.querySelector('.arrow-r');
img = bannerimg.querySelector('img');
//菜单栏滑动块
let cloud = document.querySelector('.cloud');
let nav = document.querySelector('.nav');
let lis = nav.querySelectorAll('li');
let current = 0; //起始位置
for (let i = 0; i < lis.length; i++) {
lis[i].addEventListener('mouseenter', function() {
animate(cloud, this.offsetLeft);
})
lis[i].addEventListener('mouseleave', function() {
animate(cloud, current);
})
lis[i].addEventListener('click', function() {
for (let i = 0; i < lis.length; i++) {
lis[i].style.color = '';
}
lis[i].style.color = '#00BFFF'
current = this.offsetLeft;
})
}
//图片的宽度
let imgWidth = img.offsetWidth;
//num为左右按钮计数
let num = 0;
//circle为小图标计数
let circle = 0;
let flag = true; //节流阀 防抖
//鼠标放在banner上面显示左右按钮
bannerimg.addEventListener('mouseover', function() {
arrow_l.style.display = 'block';
arrow_r.style.display = 'block';
clearInterval(timer);
timer = null;
})
bannerimg.addEventListener('mouseout', function() {
arrow_l.style.display = 'none';
arrow_r.style.display = 'none';
timer = setInterval(arrow_right, 2500);
})
//动态生成小圆圈 绑定事件
for (let i = 0; i < ul.children.length; i++) {
let li = this.document.createElement('li');
ol.appendChild(li);
li.setAttribute('index', i)
li.addEventListener('mouseover', function() {
for (let i = 0; i < ol.children.length; i++) {
ol.children[i].style.backgroundColor = 'white';
}
this.style.backgroundColor = '#00BFFF';
animate(ul, -imgWidth * i)
let index = this.getAttribute('index');
num = index;
circle = index;
})
}
ol.children[0].style.backgroundColor = '#00BFFF';
//克隆第一张图片放在最后节点上面
let firstImg = ul.children[0].cloneNode(true);
ul.appendChild(firstImg);
//左右按钮移动轮播图
arrow_r.addEventListener('click', arrow_right)
arrow_l.addEventListener('click', arrow_left)
//自动轮播
timer = setInterval(arrow_right, 2500);
// 封装右按钮函数
function arrow_right() {
if (flag) { //防抖
flag = false
if (num == ul.children.length - 1) {
ul.style.left = 0;
num = 0;
}
num++;
animate(ul, -num * imgWidth, function() {
flag = true;
})
circle++;
if (circle == ol.children.length) {
circle = 0;
}
for (let i = 0; i < ol.children.length; i++) {
ol.children[i].style.backgroundColor = 'white';
}
ol.children[circle].style.backgroundColor = '#00BFFF';
}
}
//封装左按钮函数
function arrow_left() {
if (flag) { //防抖
flag = false;
if (num == 0) {
num = ul.children.length - 1;
ul.style.left = -num * imgWidth + 'px';
}
num--;
animate(ul, -num * imgWidth, function() {
flag = true;
})
if (circle == 0) {
circle = ol.children.length;
}
circle--;
for (let i = 0; i < ol.children.length; i++) {
ol.children[i].style.backgroundColor = 'white';
}
ol.children[circle].style.backgroundColor = '#00BFFF';
}
}
})