js之缓存动画实现轮播图效果
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
* {
padding: 0;
margin: 0;
list-style: none
}
#wrap {
width: 960px;
height: 320px;
border: 2px solid red;
margin: 50px auto;
position: relative;
overflow: hidden;
}
#wrap img {
width: 960px;
height: 320px;
}
#wrap ul {
width: 3840px;
position: absolute;
}
#wrap li {
float: left;
}
#wrap p {
position: absolute;
bottom: 20px;
width: 100%;
text-align: center;
}
#wrap span {
padding: 2px 8px;
background: blue;
color: #fff;
margin-right: 4px;
cursor: pointer;
}
#wrap .active {
background: red;
}
</style>
</head>
<body>
<div id="wrap">
<!--2.图片列表-->
<ul>
<!-- <li><img src="img/1.jpg" alt=""></li>
<li><img src="img/2.jpg" alt=""></li>
<li><img src="img/3.jpg" alt=""></li>
<li><img src="img/4.jpg" alt=""></li> -->
</ul>
<p>
<!-- <span class="active">1</span><span>2</span><span>3</span><span>4</span> -->
</p>
</div>
</body>
</html>
js文件
window.onload = function() {
//1 获取元素
var ul = document.getElementsByTagName('ul')[0];
var p = document.getElementsByTagName('p')[0];
var wrap = document.getElementById('wrap');
//2 动态渲染页面
var imgArr = ['./img/1.jpg', './img/2.jpg', './img/3.jpg', './img/4.jpg'];
for (var i = 0; i < imgArr.length; i++) {
//创建li
var li = document.createElement('li');
li.innerHTML = '<img src="' + imgArr[i] + '">';
//追加到ul
ul.appendChild(li);
//创建序号按钮
var span = document.createElement('span');
span.innerText = i + 1;
p.appendChild(span);
}
//3 初始化默认样式
p.children[0].className = 'active';
//4实现自动轮播
//轮播图自动轮播 当鼠标移入的时候 停止轮播 当鼠标移出的时候 重新开始轮播
//ul的定位是 -被推出的图片个数 * 图片宽度(960)
//声明一个计数变量 用来记录从div左侧被推出去的图片个数
var n = 0;
// console.log(ul.children[0].offsetWidth) 可以获取li的宽度
//4.1 每隔2s 移动一次
function auto() {
//如果当前显示假0 就定位到 真0 之后往真1走
if (n >= 4) {
// 定位到 真0
ul.style.left = 0;
n = 0;
}
//让ul向左走一张图宽 计算图片或li的宽度
n++;
var end = -(n * 960);
bufferMove(ul, {
left: end
});
//设置序号对应 排他思想
for (var j = 0; j < p.children.length; j++) {
p.children[j].className = '';
}
// 如果当前显示的是假0 就让序号1亮起
if (n >= 4) {
p.children[0].className = 'active';
} else {
p.children[n].className = 'active';
}
}
//执行动画
var timer = setInterval(auto, 3000);
//4.2 当鼠标移入 清除定时器
wrap.onmouseover = function() {
clearInterval(timer);
}
//4.3 当鼠标移出 从新添加定时器
wrap.onmouseout = function() {
timer = setInterval(auto, 3000);
}
//5 无缝轮播
//在ul的最后面添加一张假图片 假的第一张图片
var fade = ul.children[0].cloneNode(true);
ul.appendChild(fade);
//5.1 动态修改ul宽度 ul width == li个数 * li宽度
ul.style.width = ul.children.length * 960 + 'px';
//6 点击序号实现切换
var spanS = document.getElementsByTagName('span');
for (var i = 0; i < spanS.length; i++) {
//自定义索引
spanS[i].idx = i;
spanS[i].onclick = function() {
//切换到对应图片 ul定位终点值 -图片下标 * 图宽
//由于序号下标和 图片下标一一对应,因此可以使用序号下标替代图片下标 ul定位终点值 : -序号下标 * 图宽
var end = -this.idx * 960;
bufferMove(ul, {
left: end
});
//序号亮起的问题
for (var j = 0; j < spanS.length; j++) {
spanS[j].className = '';
}
this.className = 'active';
//bug:序号轮播中没有关联 自动轮播中的n变量
//需要关联一下n变量
n = this.idx;
}
}
动画函数
//缓存动画函数
function bufferMove(ele, json, fun) { //json是一个用来接收对象的形参
//json接收的对象形式: {添加动画的属性名:终点值}
//fun用来接收回调函数
//让一个元素left移动到指定位置
//在每次添加定时器之前 先清除一次定时器 防止定时器的叠加
clearInterval(ele.timer);
//每一个添加动画效果的元素自己都应该拥有一个自己的定时器,这样才能做到互不影响
ele.timer = setInterval(function() {
//为了让所有属性都可以运动到终点 因此这里我们给一个判断标识
var flag = true; //true表示大家都执行完了
//循环整个json对象 给每一个属性都添加动画效果
for (var key in json) { //json:{width:500,height:500,opacity:50}
var attr = key; //属性名
var target = json[key]; //终点值
//1.获取起点
if (attr == 'opacity') {
var cur = getStyle(ele, attr) * 100;
} else {
var cur = parseInt(getStyle(ele, attr)); //300
}
//2.计算步长
var step = (target - cur) / 10; // 如果步长大于0 要向上取整, 步长小于0 要向下取整
//3.处理步长
step = step > 0 ? Math.ceil(step) : Math.floor(step);
//4.迈出第一只脚 确定下一步的位置
cur += step;
//6.在定位之前,判断是否有人没到终点
if (step > 0 && cur < target) {
flag = false //证明有人没到终点
} else if (step < 0 && cur > target) {
flag = false;
}
//5.第二只脚跟上 定位
if (attr == 'opacity') {
ele.style[attr] = cur / 100;
} else {
ele.style[attr] = cur + 'px';
}
}
//判断 如果大家都到终点了 flag的值为true 否则,值为false
if (flag == true) {
//清除定时器
clearInterval(ele.timer);
//在动画执行完之后 如果用户传入了 回调函数 我们就调用
if (fun) {
fun();
}
}
}, 25)
}
function getStyle(ele, attr) {
if (ele.currentStyle == undefined) { //标准浏览器
return getComputedStyle(ele)[attr];
} else { //ie8-
return ele.currentStyle[attr];
}
}
}
本文来自博客园,作者:JackieDYH,转载请注明原文链接:https://www.cnblogs.com/JackieDYH/p/17634767.html