原生js轮播图效果
- 简单的一个原生js轮播图效果,欢迎大佬指点江山,如果有萌新不懂的地方欢迎私信;
结构部分
- 准备好一个简单的HTML结构部分,记住图片一定要用 ul 的 li 来包裹,因为我们所做的轮播图是用 ul 的移动来实现的轮播效果,所以也别忘记给 ul加上 定位 position,一般我们都是用 绝对定位(至少我是用的绝对定位,不知道其他大佬是怎么做的)
- 写代码的时候可能会因为 ul 父盒子的宽度不够,不能够使 li 设置了 浮动 float 也无法在一行内显示,这时我们只要将 ul 的宽度尽量设置的大一些就好。
//focus是ul的父盒子
.focus ul {
position: absolute;
left: 0;
padding: 0;
margin: 0;
list-style: none;
width: 800%;
}
.focus ul li {
width: 590px;
float: left;
}
.focus ul li img {
width: 100%;
}
js部分
鼠标移入移出
-
如果不想要做这部分的话可以直接跳过,对最后的图片轮播效果实现并没有太大的影响。
-
这部分也比较简单,我们只需要添加 onmouseenter 和 onmouseleave 事件就可以了,设置左右箭头的display 属性。
-
鼠标移入时
focus.addEventListener('mouseenter', function () {
arrow_l.style.display = 'block';
arrow_r.style.display = 'block';
});
- 鼠标移出时
focus.addEventListener('mouseleave', function () {
arrow_l.style.display = 'none';
arrow_r.style.display = 'none';
});
图片左下角小圆点
创建小圆点
- 因为可能不知道会有多少张图片,所以我们最好的方法是通过 for 循环来动态来创建小圆点
for (var i = 0; i < ul.children.length; i++)
var li = document.createElement('li');
- 添加到 ol 里面
ol.appendChild(li);
- 同时在创建 li 的同时添加一个自定义属性,点击小圆点时,获取自定义属性来移动图片
li.setAttribute(‘index’, i);
点击小圆点
- 我们在创建小圆点的同时可以同时给 li 添加绑定事件,每次点击时我们给当前的 li 添加我们写好的类名 current 或者直接修改背景颜色,其他的 li 使用 排他思想 修改类名或者修改背景颜色。
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = '';
}
// 留下我自己 当前的小li 设置current 类名
this.className = 'current';
图片移动
- 我们点击 li 时同获取当前的 li 的自定义属性
var index = this.getAttribute(‘index’);
- 然后调用之前封装好的一个动画函数 animate (动画函数请往下看)
animate(ul, -index * focusWidth); //focusWidth = focus.offsetWidth;
- 这样坐下角的小圆点的创建和点击事件基本上就做完了
图片无缝滚动的原理
- 图片之所以会无缝滚动,是因为我们看到的最后一张图片实际上我们克隆的第一张图片,放到最后;到我们克隆的图片,我们下一次点击时 ul 的 left 值将会等于0,然后在继续往后滚动,由于我们设置了溢出隐藏,所以 ul 的 left 值等于0时,我们的肉眼并不能发现直观的变化,所以就形成了无缝滚动。
//克隆第一张图片(li)放到ul 最后面
var first = ul.children[0].cloneNode(true);
ul.appendChild(first);
按钮的点击
右按钮的点击
- 我们先准备一个全局变量 num (名字随意),之后也会用来同步左下角小圆点的状态
- 给右按钮添加点击事件,每次点击时 num 自加;
- 并且如果 num 的值大于 图片长度的索引号时,让 num 等于0,并且让 ul 的 left 值等于0;这样图片就会再次回到第一张
- 然后我们通过动画函数移动 ul;
if (num == ul.children.length - 1) {
ul.style.left = 0;
num = 0;
}
num++;
animate(ul, -num * focusWidth)
});
- 然后我们又准备一个全局变量 circle 点击时,左下角的小圆点也会跟着一起移动
circle++;
// 如果circle =4 说明走到最后我们克隆的这张图片了 我们就复原
if (circle == ol.children.length) {
circle = 0;
}
// 先清除其余小圆圈的current类名
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = '';
}
// 留下当前的小圆圈的current类名
ol.children[circle].className = 'current';
左按钮的点击与右按钮相似
自动轮播部分
- 自动轮播部分我们只需要设置一个循环定时器,每隔几秒钟调用我们右按钮的点击事件便可实现自动轮播
var timer = setInterval(function () {
//手动调用点击事件
arrow_r.click();
}, 2000);
- 鼠标移入时,清除定时器;鼠标移出时,就重新启动定时器;
- 鼠标移入
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);
});
点击按钮与小圆点同步
- 我们点击右按钮时虽然小圆点可以同步添加类名,但是如果点击小圆点移动图片后在次点击按钮,小圆点的激活顺序就会与我们想象的不同,这时我们只需要把 li 的自定义属性赋值给全局变量 num 和 全局变量 circle 就可以解决这个问题;
num = circle = index;
动画函数
- 我们通过改变元素的 left 属性来移动元素
- 使用循环定时器可以不停移动元素
- 当条件满足时,就清除定时器;
//obj 是我们要移动的那个元素,target 移动的位置,callback 回调函数
function animate(obj, target, callback) {
//每次调用这个函数时我们先清除定时器,防止速度过快
clearInterval(obj.timer);
obj.timer = setInterval(function () {
//手动设置一个缓动效果
var step = (target - obj.offsetLeft) / 10;
//如果小于0就向下取整,大于0就向上取整
step = step < 0 ? Math.floor(step) : Math.ceil(step);
if (obj.offsetLeft == target) {
clearInterval(obj.timer);
timer = null;
//逻辑与的短路运算
callback && callback();
}
obj.style.left = obj.offsetLeft + step + 'px'
}, 15)
}
代码链接
下面是我写的代码链接
代码链接