案例:网页轮播图
2021-02-16 16:19
标签:cal 实现 注意 code div 距离 center == top 轮播图也称为焦点图,是网页中比较常见的网页特效。 功能需求: 1. 鼠标经过轮播图模块,左右按钮显示,鼠标离开则隐藏左右按钮。 2. 点击右侧按钮一次,图片往左播放一张,以此类推,左侧按钮同理。 3. 图片播放的同时,下面小圆圈模块跟随一起变化。 4. 点击小圆圈,可以播放相应图片。 5. 鼠标不经过轮播图,轮播图也会自动播放图片。 6. 鼠标经过轮播图模块,自动播放停止。 因为js较多,我们单独新建js文件夹,再新建js文件,引入页面中。此时需要添加load事件。 需要实现功能的具体思路如下: ① 动态生成小圆圈: ② 点击小圆圈滚动图片: ③ 点击右侧按钮一次,就让图片滚动一张: 实现无缝滚动的步骤:克隆第一张图片,克隆ul中第一个li,cloneNode(true)深克隆复制里面的子节点,然后添加到ul的最后面(appendChild) ④ 点击右侧按钮,小圆圈跟随变化: ⑤ 自动播放功能: ⑥ 节流阀功能:防止轮播图按钮点击造成播放过快的问题 核心代码如下: 封装的动画函数animate.js文件: 出现一个bug1:当点击小圆圈移动到指定图片后,再点击下一张的按钮,结果图片却返回上一张了。这是因为当前的索引号index与num并没有产生关联。解决办法:在小圆圈的点击事件里,获取到data-index属性后,需要赋值给num(控制图片播放的序号)。 出现第二个bug2:这样修改之后,虽然图片能正确显示到下一张,但是小圆圈却返回到上一个去了。这是因为当前的索引号index与circle并没有产生关联。解决办法:在小圆圈的点击事件里,获取到data-index属性后,需要赋值给circle(控制小圆圈播放的序号)。 只有这样才能保持同步。 注意的是,num、circle、timer等变量都是在后面声明的,但是却在前面可以调用,虽然代码是从上往下执行的,但是却能正常使用,这是因为JS有预定义变量的功能。 案例:网页轮播图 标签:cal 实现 注意 code div 距离 center == top 原文地址:https://www.cnblogs.com/zcy9838/p/12961973.html
div class="focus">
a href="javascript:;" class="arrow-l">?a>
a href="javascript:;" class="arrow-r">?a>
ul>
li>a href="#">img src="upload/focus.jpg" alt="">a>li>
li>a href="#">img src="upload/focus1.jpg" alt="">a>li>
li>a href="#">img src="upload/focus2.jpg" alt="">a>li>
li>a href="#">img src="upload/focus3.jpg" alt="">a>li>
ul>
ol class="circle">
ol>
div>
/* CSS样式 */
.focus {
position: relative;
width: 721px;
height: 455px;
overflow: hidden;
}
.focus ul {
/* 注意:轮播图中是ul在左右的滚动,不是设置小li
动画必须要有定位,所以要给ul加上定位 */
position: absolute;
top: 0;
left: 0;
width: 600%;
}
.focus ul li {
/* 注意:这里的四张图片并不能浮动起来
因为一张图片设置的与父盒子focus一样大
所以即使浮动起来了,一行也显示不下,而导致并没有想要的浮动效果
解决办法:使li的父盒子ul的宽度足够大,然后让focus盒子溢出隐藏 */
float: left;
}
.arrow-l,
.arrow-r {
display: none;
/* 子绝父相:子元素绝对定位,则父元素必须是相对定位 */
position: absolute;
/* 下面两句代码为水平居中的方式 */
/* 定位到父元素的居中位置 */
top: 50%;
/* 还需要往上走自己高度的一半值 */
margin-top: -20px;
/* a标签没有大小,常规来说不能给定宽高 但是浮动下的绝对定位的元素可以给定大小*/
width: 24px;
height: 40px;
/* 背景设置为半透明状 */
background: rgba(0, 0, 0, .3);
/* 文字水平居中用text-align 垂直居中用line-height */
text-align: center;
line-height: 40px;
color: #fff;
font-family: ‘icomoon‘;
font-size: 18px;
/* ul和arrow-l、arrow-r都有定位,就有层级关系,
ul的层级压住了左右按钮,因此需要增加层级 */
z-index: 2;
}
.arrow-r {
/* 指定盒子参照相对物右边界向左偏移 */
right: 0;
}
.circle {
position: absolute;
bottom: 10px;
left: 50px;
}
.circle li {
float: left;
width: 8px;
height: 8px;
border: 2px solid rgba(255, 255, 255, 0.5);
margin: 0 3px;
/* 使li变成圆形 */
border-radius: 50%;
/* 鼠标经过时显示为小手 */
cursor: pointer;
}
.current {
background-color: #fff;
}
function animate(obj, target, callback) {
// console.log(callback); callback = function() {} 调用的时候 callback()
// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function() {
// 步长值写到定时器的里面
// 把我们步长值改为整数 不要出现小数的问题
// var step = Math.ceil((target - obj.offsetLeft) / 10);
var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
// 停止动画 本质是停止定时器
clearInterval(obj.timer);
// 回调函数写到定时器结束里面
// if (callback) {
// // 调用函数
// callback();
// }
// 注意此处的优化代码
callback && callback();
}
// 把每次加1 这个步长值改为一个慢慢变小的值 步长公式:(目标值 - 现在的位置) / 10
obj.style.left = obj.offsetLeft + step + ‘px‘;
}, 15);
}
// JS逻辑代码
window.addEventListener(‘load‘, function() {
// 1. 获取元素
var arrow_l = document.querySelector(‘.arrow-l‘);
var arrow_r = document.querySelector(‘.arrow-r‘);
var focus = document.querySelector(‘.focus‘);
// 图片的宽度
var focusWidth = focus.offsetWidth;
// 2. 鼠标经过focus就显示隐藏左右按钮
focus.addEventListener(‘mouseenter‘, function() {
arrow_l.style.display = ‘block‘;
arrow_r.style.display = ‘block‘;
// 鼠标经过则清除自动播放的清除器
clearInterval(timer);
// 清除定时器变量
timer = null;
});
focus.addEventListener(‘mouseleave‘, function() {
arrow_l.style.display = ‘none‘;
arrow_r.style.display = ‘none‘;
// 鼠标离开则重新开启定时器
timer = setInterval(function() {
// 手动调用点击事件
arrow_r.click();
}, 2000);
});
// 3. 动态生成小圆圈,有几张图片就生成几个小圆圈
var ul = focus.querySelector(‘ul‘);
var ol = focus.querySelector(‘.circle‘);
for (var i = 0; i) {
// 创建一个小li
var li = document.createElement(‘li‘);
// 创建好li后,立即设置当前小圆圈的索引号,通过自定义属性来做
li.setAttribute(‘data-index‘, i);
// 把小li插入到ol里面
ol.appendChild(li);
// 4. 小圆圈的排他思想:我们可以直接在生成小圆圈的同时直接绑定点击事件
li.addEventListener(‘click‘, function() {
// 清除其所有小li的current样式
for (var i = 0; i ) {
ol.children[i].className = ‘‘;
}
// 将当前点击的小li设置current样式
this.className = ‘current‘;
// 点击小圆圈,移动图片。注意:移动的是ul,不是小li
// ul的移动距离 = 小圆圈的索引号 * 图片的宽度(注意是负值)
// 当我们点击了某个小li,就拿到当前小li的索引号
var index = this.getAttribute(‘data-index‘);
// 当我们点击了某个小li,就拿到当前小li的索引号给num
num = index;
// 当我们点击了某个小li,就拿到当前小li的索引号给circle
circle = index;
// num = circle = index;
animate(ul, -index * focusWidth);
});
}
// 把 ol 里面的第一个小li设置类名为 current
ol.children[0].className = ‘current‘;
// 6. 克隆第一张图片(li)放到ul的最后面(注意,克隆的图片一定要写到生成小圆圈的下面)
var first = ul.children[0].cloneNode(true);
ul.appendChild(first);
// 7. 点击右侧按钮,图片滚动一张
var num = 0;
// circle控制小圆圈的播放
var circle = 0;
// flag 节流阀
var flag = true;
arrow_r.addEventListener(‘click‘, function() {
if (flag) {
flag = false; // 关闭节流阀
// 如果走到了最后复制的一张图片,此时ul需要快速复原,left值改为0
if (num == ul.children.length - 1) {
ul.style.left = 0;
num = 0;
}
num++;
animate(ul, -num * focusWidth, function() {
// 等待动画执行完毕才打开节流阀
flag = true;
});
// 8. 点击右侧按钮,小圆圈跟随一起变化,可以再声明一个变量控制小圆圈的播放
circle++;
// 如果circle == 4 说明走到最后克隆的这张图片了,就需要复原
if (circle == ol.children.length) {
circle = 0;
}
// 调用设置当前小圆圈为current样式的函数
circleChange();
}
});
// 9. 左侧按钮做法
arrow_l.addEventListener(‘click‘, function() {
if (flag) {
flag = false; // 关闭节流阀
// 如果走到了最后复制的一张图片,此时ul需要快速复原,left值改为0
if (num == 0) {
num = ul.children.length - 1;
// 千万别忘了加‘px‘
ul.style.left = -num * focusWidth + ‘px‘;
}
num--;
animate(ul, -num * focusWidth, function() {
// 等待动画执行完毕才打开节流阀
flag = true;
});
// 8. 点击右侧按钮,小圆圈跟随一起变化,可以再声明一个变量控制小圆圈的播放
circle--;
// 如果circle
if (circle ) {
circle = ol.children.length - 1;
}
// 调用设置当前小圆圈为current样式的函数
circleChange();
}
});
// 设置当前小圆圈为current样式
function circleChange() {
// 先清除其余小圆圈的current类名
for (var i = 0; i ) {
ol.children[i].className = ‘‘;
}
// 留下当前的小圆圈的current类名
ol.children[circle].className = ‘current‘;
}
// 10. 自动播放轮播图
var timer = setInterval(function() {
// 手动调用点击事件
arrow_r.click();
}, 2000);
});