实现效果
实现分析:
效果分析:
①鼠标移入轮播图后显示左右箭头,鼠标移出轮播图后会隐藏左右箭头
②通过实现效果分析,可得出该5张轮播图的图片设置了5中不同的样式,我们可 以将该五种样式保存到数组中,方便每次点击箭头时对每张图的样式进行切换
代码分析:
①先封装一个动画函数,以便于点击时使用该函数进行图片的切换
由于需要考虑到复用性,可能传递到动画的参数都不一样,如实现动画效果的对象、动画改变的参数(如:上下左右移动,宽度、高度、透明度变化等)。
【如:在本次轮播图中,需要改变的是 宽:width ;离父元素的上侧距离top;离父元素的左侧边距离 left ;透明度opacity 层级 z-index】
因此:我们应该设置如下三个参数:动画对象、该对象需要改变的参数对象(即:以防止以后复用该动画函数时传递过来的参数不包含本次用到的属性,如:将该对象需要在本次动画所改变的参数width、top、left、opacity、z-index放到对象参数中)和回调函数callback(防止某些动画的开始的前提是在本次运动后才能执行或者结束本次动画时需要执行其他操作)
function slowDown(obj, options, callback) {
//在执行本次动画前,先清除定时器,避免上一次定时器影响
clearInterval(obj.timer)
obj.timer = setInterval(function () {
// 假设都到目标位置
let flag = true;
// 用for..in..循环遍历options
for (let attr in options) {
// 处理opacity
//判断本次获取到的对象属性是否为opacity(即:透明度)
if (attr == 'opacity') {
//因为透明度的取值范围为0-1,因此防止下面取整所影响,所以需要乘100
//target为目标值
let target = options[attr] * 100
//由于obj.style只能获取到行内设置的样式
//通过getComputedStyle(obj)可以获取obj中的css样式值
let curV = getComputedStyle(obj)[attr] * 100
//step为步长,即每次运动的长度,除10可以更改,这里就用每次走总数的十分之一为例
let step = (target - curV) / 10
// 根据运动方向来决定是向右取整还是向左取整
step = step >= 0 ? Math.ceil(step) : Math.floor(step);
// 移动后位置
//由于上面乘了100,所以这里需要除100
//nextV为本次动画的所需达到的值
let nextV = (curV + step) / 100
//将本次动画的所需达到的值赋值给该动画对象的属性中
obj.style[attr] = nextV
// 判断只要有一个没有到达目标值就继续
if (nextV * 100 != target) {
flag = false
}
//如果该对象属性为层级zindex,则直接赋值即可,因为层级是直接设置的,没有动画效果
} else if (attr === 'zIndex' || attr === 'z-index') {
obj.style.zIndex = options[attr]
} else {
//如果是其他属性(因为本次案例中,只有z-index和opacity是不带单位的,其他属性需要有px)
let target = options[attr]
let curV = parseInt(getComputedStyle(obj)[attr])
let step = (target - curV) / 10
// 根据方向来决定是向右取整,还是向左取整
step = step >= 0 ? Math.ceil(step) : Math.floor(step);
let nextV = curV + step;
obj.style[attr] = nextV + 'px';
// 判断只要有1个没有到达目标值就
if (nextV != target) {
flag = false;
}
}
}
//判断是否所有属性都达到了目标值
if (flag) {
//如果都达到即停止定时器
clearInterval(obj.timer);
//判断是否传递进来其他回调函数
if (typeof (callback) === 'function') {
callback();
}
}
}, 30);
}
②获取需要操作的元素对象
// 获取操作的元素
//装轮播图的父元素
let oWrap = document.querySelector('.wrap');
//装轮播图中左右箭头的父元素
let oArrow = document.querySelector('.arrow');
//右箭头元素
let oRight = document.querySelector('#arrRight');
//左箭头元素
let oLeft = document.querySelector('#arrLeft');
//装轮播图图片的li
let oLis = document.querySelectorAll('.wrap li');
③移入轮播图时显示左右箭头
为装轮播图的父元素oWrap 绑定鼠标移入onmouseover、移出事件onmouseout,鼠标移入轮播图时,显示左右箭头,移出时隐藏轮播图,这里通过改变父元素oWrap 的opacity值来实现
// 鼠标移入事件
oWrap.onmouseover = function () {
oArrow.style.opacity = 1;
}
oWrap.onmouseout = function () {
oArrow.style.opacity = 0;
}
④切换时需要用到的样式数组
// 当前效果,有5组样式
let config = [{
width: 600,
top: 70,
left: 600,
opacity: 0.8,
'z-index': 3
},
{
width: 400,
top: 20,
left: 750,
opacity: 0.2,
'z-index': 2
},
{
width: 400,
top: 20,
left: 50,
opacity: 0.2,
'z-index': 2
},
{
width: 600,
top: 70,
left: 0,
opacity: 0.8,
'z-index': 3
},
{
width: 800,
top: 120,
left: 200,
opacity: 1,
'z-index': 4
}
];
⑤为每个li设置样式
通过for循环,将放轮播图的图片的li设置对应的样式
function setStyle(){
// 创建一个函数,为每个li应用相应的样式
for(let i=0;i<oLis.length;i++){
调用上面封装的动画函数,并且把第i个li、和对应的第i个样式数组中的样式传递进去
slowDown(oLis[i],config[i])
}
}
//初次打开页面时先调用一次,否则页面中的轮播图没有效果显示
setStyle()
⑥为左右箭头绑定点击事件
每次点击时,调用上面的setStyle()函数,为li重新赋值
oLeft.onclick=function(){
// 将样式组件里的最后的元素移动到和数组的头部
config.unshift(config.pop())
setStyle()
}
oRight.onclick = function(){
// 将样式数组里的前面的元素移动到数组的尾部
config.push(config.shift());
setStyle();
}
完整代码
HTML部分:
<div class="wrap" id="wrap">
<div class="slide" id="slide">
<ul>
<li class="five"><a href="#"><img src="images/bingbing.jpg" alt="" /></a></li>
<li class="four"><a href="#"><img src="images/lingengxin.jpg" alt="" /></a></li>
<li class="three"><a href="#"><img src="images/yuanyuan.png" alt="" /></a></li>
<li class="two"><a href="#"><img src="images/slidepic4.jpg" alt="" /></a></li>
<li class="one"><a href="#"><img src="images/slidepic5.jpg" alt="" /></a></li>
</ul>
<div class="arrow" id="arrow">
<a href="javascript:;" class="prev" id="arrLeft"></a>
<a href="javascript:;" class="next" id="arrRight"></a>
</div>
</div>
</div>
CSS部分:
/*初始化 reset*/
* {
margin: 0;
padding: 0
}
body {
font: 12px/1.5 "Microsoft YaHei", "微软雅黑", SimSun, "宋体", sans-serif;
color: #666;
}
ol,
ul {
list-style: none
}
a {
text-decoration: none
}
img {
border: 0;
vertical-align: top;
}
textarea {
outline: none;
}
a,
button {
cursor: pointer;
}
.wrap {
width: 1200px;
margin: 100px auto;
border: 1px solid red;
}
.slide {
height: 500px;
position: relative;
}
.slide li {
position: absolute;
left: 200px;
top: 0;
}
.slide li img {
width: 100%;
}
.arrow {
opacity: 0;
}
.prev,
.next {
width: 76px;
height: 112px;
position: absolute;
top: 50%;
margin-top: -56px;
/*background-color: red;*/
background: url(./images/prev.png) no-repeat;
z-index: 99;
}
.next {
right: 0;
background-image: url(./images/next.png);
}
JS部分:
// 当前效果,有5组样式
let config = [{
width: 600,
top: 70,
left: 600,
opacity: 0.8,
'z-index': 3
},
{
width: 400,
top: 20,
left: 750,
opacity: 0.2,
'z-index': 2
},
{
width: 400,
top: 20,
left: 50,
opacity: 0.2,
'z-index': 2
},
{
width: 600,
top: 70,
left: 0,
opacity: 0.8,
'z-index': 3
},
{
width: 800,
top: 120,
left: 200,
opacity: 1,
'z-index': 4
}
];
// 获取操作的元素
let oWrap = document.querySelector('.wrap');
let oArrow = document.querySelector('.arrow');
let oRight = document.querySelector('#arrRight');
let oLeft = document.querySelector('#arrLeft');
let oLis = document.querySelectorAll('.wrap li');
// 鼠标移入事件
oWrap.onmouseover = function () {
oArrow.style.opacity = 1;
}
oWrap.onmouseout = function () {
oArrow.style.opacity = 0;
}
function setStyle(){
// 创建一个函数,为每个li应用相应的样式
for(let i=0;i<oLis.length;i++){
slowDown(oLis[i],config[i])
}
}
setStyle()
oLeft.onclick=function(){
// 将样式组件里的最后的元素移动到和数组的头部
config.unshift(config.pop())
setStyle()
}
oRight.onclick = function(){
// 将样式数组里的前面的元素移动到数组的尾部
config.push(config.shift());
setStyle();
}
function slowDown(obj, options, callback) {
clearInterval(obj.timer)
obj.timer = setInterval(function () {
// 假设都到目标位置
let flag = true;
// 遍历options
for (let attr in options) {
// 处理opacity
if (attr == 'opacity') {
let target = options[attr] * 100
let curV = getComputedStyle(obj)[attr] * 100
let step = (target - curV) / 10
// 根据方向来决定是向右取整还是向左取整
step = step >= 0 ? Math.ceil(step) : Math.floor(step);
// 移动后位置
let nextV = (curV + step) / 100
obj.style[attr] = nextV
// 判断只要有一个没有到达目标值就继续
if (nextV * 100 != target) {
flag = false
}
} else if (attr === 'zIndex' || attr === 'z-index') {
obj.style.zIndex = options[attr]
} else {
let target = options[attr]
let curV = parseInt(getComputedStyle(obj)[attr])
let step = (target - curV) / 10
// 根据方向来决定是向右取整,还是向左取整
step = step >= 0 ? Math.ceil(step) : Math.floor(step);
let nextV = curV + step;
obj.style[attr] = nextV + 'px';
// 判断只要有1个没有到达目标值就
if (nextV != target) {
flag = false;
}
}
}
if (flag) {
clearInterval(obj.timer);
if (typeof (callback) === 'function') {
callback();
}
}
// console.log(curV,step,nextV);
}, 30);
}