轮播图特效算是各大电商网站的必备特效之一,原理其实很简单,用到少量的知识点, DOM基础操作,计时器,对于新手难点就在于,图片滚动时的下方小圆点也要实现同步滚动,新手可以学习下,大佬欢迎指点!!话不多说 先上代码,样式的话这里就随便写写了, 不要在意那些细节,我们注重功能
HTML部分
<div id="container">
<ul id="imgs">
<li><a href="#"><img src="imgs/4.jpg">a>li>
<li><a href="#"><img src="imgs/1.jpg">a>li>
<li><a href="#"><img src="imgs/2.jpg">a>li>
<li><a href="#"><img src="imgs/3.jpg">a>li>
<li><a href="#"><img src="imgs/4.jpg">a>li>
<li><a href="#"><img src="imgs/1.jpg">a>li>
ul>
<div id="pages">
<i class="current">i>
<i>i>
<i>i>
<i>i>
div>
<div id="prev"><div>
<div id="next">>div>
div>
CSS部分
<style type="text/css">
* {
margin: 0;
padding: 0;
}
#container {
width: 590px;
height: 470px;
position: relative;
margin: 50px auto;
border: 1px solid #000;
overflow: hidden;
}
ul {
position: absolute;
left : -590px;
top: 0;
width: 3540px;
height: 470px;
}
#imgs li {
width: 590px;
height: 470px;
list-style: none;
float: left;
}
#pages {
position: absolute;
height: 30px;
width: 100%;
bottom: 0;
background: #000;
}
#pages i {
display: inline-block;
width: 20px;
height: 20px;
margin: 5px;
background: #fff;
border-radius: 10px;
}
#pages i.current {
background: #f00;
}
#prev, #next {
width: 40px;
height: 60px;
background: #000;
position: absolute;
top: 0;
bottom: 0;
margin: auto;
color: #fff;
font-size: 30px;
text-align: center;
line-height: 60px;
}
#next {
right: 0;
}
style>
接下来是重点了,来我要开始表演了
JavaScript部分,实现三个功能
- 1.自动轮播切换图片(当然还有那种淡入淡出的轮播图,今天这里写位移的轮播图,我觉得更炫酷)
- -2. 点击左右箭头按钮也能前后切换图片,且鼠标滑入到banner图中后 图片的轮播效果要停止的,(不然何来用户体验)
- -3.鼠标滑入(或者点击)底部小圆点时,也能跳转到对应的图片,
- - 差不多也就这些效果了 来先看看JS代码热热身。
- (这里用到了自己封装的一个小的JS工具库(文章底部有代码),用到了
- 获取元素ID,设置CSS属性,及运动函数三个功能)
<script>
var lis = $("li"), // 所有图片盒子
length = lis.length, // 总图片张数
ul = $("#imgs"), // 运动元素
currentIndex = 1, // 当前索引
nextIndex = 2, // 即将索引
circles = $("i"), // 小圆点
//为了防止运动函数计时器叠加 造成BUG
isRunning = false; // true:正在执行切换动画 false:未执行切换动画
// 轮播切换
var move = function() {
// 计算轮播过程中的定位
var _left = -1 * nextIndex * 590;
// 运动
animate(ul, {left: _left}, 200, function(){
if (nextIndex >= length) { // 向左
currentIndex = 1;
nextIndex = 2;
ul.style.left = "-590px";
} else if (currentIndex <= 0) { // 向右
currentIndex = length - 2;
nextIndex = length - 1;
ul.style.left = -1 * (length - 2) * 590 + "px";
}
// 修改标记,可以继续切换
isRunning = false;
});
// 小圆点样式
// 找出变红色小圆点的索引
var redIndex = nextIndex - 1;
if (redIndex >= length - 2)
redIndex = 0;
else if(redIndex < 0)
redIndex = length - 3;
for(var i = 0; i < length - 2; i++) {
circles[i].className = ""; //清空所有小圆点样式
}
circles[redIndex].className = "current";//鼠标进入的小圆点加上样式
// 修改索引
currentIndex = nextIndex;
nextIndex++;
}
// 自动轮播
var timer = setInterval(move, 3000); //开启定时器
// 鼠标移入/移出容器
$("#container").onmouseenter = function() {
clearInterval(timer);
}
$("#container").onmouseleave = function() {
timer = setInterval(move, 3000);
}
// 小圆点点击:事件委派
$("#pages").onclick = function(e) {
var src = e.target;
if (src.nodeName === "I") {
if (!isRunning) {
// 获取当前点击的小圆点在所有小圆点中的索引
var index = Array.from(circles).indexOf(src);
// 即将显示的图片索引
nextIndex = index + 1;
// 调用轮播切换函数
move();
// 修改标记,当前正在执行切换动画
isRunning = true;
}
}
}
// 向前
$("#prev").onclick = function() {
if (!isRunning) {
nextIndex = currentIndex - 1;
move();
// 修改标记,当前正在执行切换动画
isRunning = true;
}
}
// 向后
$("#next").onclick = function() {
if (!isRunning) {
move();
// 修改标记,当前正在执行切换动画
isRunning = true;
}
}
$("#container").onselectstart = function(e){
e.preventDefault();
}
script>
总结一下,
实现原理,轮播图片总计四张,当向右切换到最后一张的时候需要切换到第一张,但是 直接跳转第一张,太明显了,用户体验不好, 很多轮播图中基本都是 ,在第一张图之前克隆最后一张图,在最后一张图之后克隆第一张图,说到这 ,可能新手有点懵,这里给一张图 理解理解
黑色框是原四张图 ,当走到第四张图的时候下一张还是第一张的图样,在最后一张图在做跳转,同样的图跳转的时候,肉眼是看不清的,这里也就实现了无缝轮播的原理!
这里偷了个懒 手动添加克隆的图片,也可以用JS代码生成
下面把刚才说的封装的小型JS库分享一下
//获取元素
function $(selector, context) {
// 默认在 document 后代查找
context = context || document;
// 判断
if (selector.indexOf("#") === 0) // id
return document.getElementById(selector.slice(1));
if (selector.indexOf(".") === 0) // className
return byClass(selector.slice(1), context);
// element
return context.getElementsByTagName(selector);
}
**
* 运动框架:线性运动
* @param element 待添加运动动画效果的DOM元素
* @param options 多属性运动配置选项
* @param speed 限定运动的总时间
* @param fn 运动结束后需要继续执行的函数
*/
function animate(element, options, speed, fn) {
// 将在 element 元素上已有的运动动画效果停止
clearInterval(element.timer);
// 计算起始值、范围值
var start = {}, range = {};
for (var attr in options) {
start[attr] = parseFloat(css(element, attr));
range[attr] = options[attr] - start[attr];
}
// 记录运动开始时间
var startTime = new Date().getTime();
// 启动计时器,运动,将计时器id缓存在 element 上
element.timer = setInterval(function(){
// 计算实际运动时间
var elapsed= Math.min(new Date().getTime() - startTime, speed);
// 每个属性计算当前值
for (var attr in options) {
// 根据线性运动公式计算
var result = elapsed * range[attr] / speed + start[attr];
// 设置CSS
element.style[attr] = result + (attr === "opacity" ? "" : "px");
}
// 判断是否停止计时器
if (elapsed === speed) {
// 停止计时器
clearInterval(element.timer);
// 如果有运动结束后执行的函数,则调用
fn && fn();
}
}, 1000/60);
}
以上两个封装函数,通过这两个函数还可以改一下效果,淡入淡出的效果,
这里依赖annimate函数
* 运动框架:淡入
* @param element 待添加运动动画效果的DOM元素
* @param speed 限定运动的总时间
* @param fn 运动结束后需要继续执行的函数
*/
function fadeIn(element, speed, fn) {
element.style.display = "block";
element.style.opacity = 0;
animate(element, {opacity: 1}, speed, fn);
}
/**
* 运动框架:淡出
* @param element 待添加运动动画效果的DOM元素
* @param speed 限定运动的总时间
* @param fn 运动结束后需要继续执行的函数
*/
function fadeOut(element, speed, fn) {
animate(element, {opacity: 0}, speed, function() {
element.style.display = "none";
fn && fn();
});
}
后续待更新