最近在看移动端开发知识点的时候,刚好看到移动端轮播图,想着不如和之前pc端的轮播图放在一起做个记录,再回顾一遍一些基础知识点。
- 轮播图的几个基础功能点:
- 自动无缝切换轮播图片
- 点击按钮切换图片
- 移动端手指滑动切换图片
- 移动端手机滑动短距离图片吸附回去
- 指示器随着图片滚动而改变
1.无缝轮播图(仅简单自动轮播,通过改变绝对定位left值来实现滚动的效果,无其他任何功能点)
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
* {
margin: 0;
padding: 0;
}
ul {
list-style: none;
}
img {
vertical-align: top;
width: 300px;
}
/*取消图片底部3像素距离*/
.box {
width: 300px;
height: 200px;
margin: 100px auto;
background-color: pink;
border: 1px solid red;
position: relative;
overflow: hidden;
}
.box ul li {
float: left;
}
.box ul {
width: 1500px;
position: absolute;
left: 0;
top: 0;
}
</style>
</head>
<body>
<div class="box" id="screen">
<ul>
<li><img src="imagess/01.jpg" alt=""/></li>
<li><img src="imagess/02.jpg" alt=""/></li>
<li><img src="imagess/03.jpg" alt=""/></li>
<li><img src="imagess/04.jpg" alt=""/></li>
<li><img src="imagess/01.jpg" alt=""/></li>
</ul>
</div>
<script>
//根据id获取元素对象
function my$(id) {
return document.getElementById(id);
}
let current = 0;
//移动函数
function f1() {
current -= 10;
let ulObj = my$("screen").children[0];
if (current < -1200) {
ulObj.style.left = "0px";
current = 0
} else {
ulObj.style.left = current + "px";
}
}
//定时移动
let timer = setInterval(f1, 50);
my$("screen").onmouseover = function () {
//鼠标移上图片停止滚动--即清除定时器
clearInterval(timer);
}
my$("screen").onmouseout = function () {
//鼠标移开图片开始滚动--即重新开启定时器
timer = setInterval(f1, 50);
}
</script>
</body>
</html>
2.焦点切换轮播图(仅简单点击按钮切换轮播的图片,封装了一个简单的动画函数,无其他任何功能点)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
body, ul, ol, li, img {
margin: 0;
padding: 0;
list-style: none;
}
#box {
width: 520px;
height: 280px;
padding: 5px;
position: relative;
border: 1px solid #ccc;
margin: 100px auto 0;
}
.ad {
width: 520px;
height: 280px;
overflow: hidden;
position: relative;
}
#box img {
width: 520px;
}
.ad ol {
position: absolute;
right: 10px;
bottom: 10px;
}
.ad ol li {
width: 20px;
height: 20px;
line-height: 20px;
border: 1px solid #ccc;
text-align: center;
background: #fff;
float: left;
margin-right: 10px;
cursor: pointer;
_display: inline;
}
.ad ol li.current {
background: yellow;
}
.ad ul li {
float: left;
}
.ad ul {
position: absolute;
top: 0;
width: 2940px;
}
.ad ul li.current {
display: block;
}
#focusD {
display: none;
}
#focusD span {
width: 40px;
height: 40px;
position: absolute;
left: 5px;
top: 50%;
margin-top: -20px;
background: #000;
cursor: pointer;
line-height: 40px;
text-align: center;
font-weight: bold;
font-family: '黑体';
font-size: 30px;
color: #fff;
opacity: 0.3;
border: 1px solid #fff;
}
#focusD #right {
right: 5px;
left: auto;
}
</style>
</head>
<body>
<div id="box" class="all">
<div class="ad">
<ul id="imgs">
<li><img src="images/01.jpg"/></li>
<li><img src="images/02.jpg"/></li>
<li><img src="images/03.jpg"/></li>
<li><img src="images/04.jpg"/></li>
<li><img src="images/05.jpg"/></li>
</ul>
</div><!--相框-->
<div id="focusD"><span id="left"><</span><span id="right">></span>
</div>
</div>
<script>
//根据id获取元素对象
function my$(id) {
return document.getElementById(id);
}
//获取box
let box = my$("box");
//获取相框ad
let ad = box.children[0];
let width = ad.offsetWidth;
let ulObj = ad.children[0];
//获取ul对象
//获取左右焦点的div
let focusD = my$("focusD");
//第一个鼠标移入box显示左右两个焦点按钮
box.onmouseover = function () {
focusD.style.display = "block";
}
box.onmouseout = function () {
focusD.style.display = "none";
}
let count = 0;
//点击左右两个焦点按钮移动相框
my$("left").onclick = function () {
if (count > 0) {
count--;
animate(ulObj, -count * width);
}
}
my$("right").onclick = function () {
//点击一次移动一次
if (count < ulObj.children.length - 1) {
count++;
animate(ulObj, -count * width);
}
}
//公共的任意对象移动指定位置
function animate(element, target) {
//清除一次
clearInterval(element.timerId);
//定时器开始
element.timerId = setInterval(function () {
//获取当前元素的left
let current = element.offsetLeft;
let step = 10;
step = current < target ? step : -step;
current += step;
if (Math.abs(target - current) > Math.abs(step)) {
element.style.left = current + "px";
} else {
clearInterval(element.timerId);
element.style.left = target + "px";
}
}, 10)
}
</script>
</body>
</html>
3.基础功能完整的轮播图(包含自动轮播,焦点切换图片,指示器切换图片,指示器随着图片变化而变化)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
* {
padding: 0;
margin: 0;
list-style: none;
border: 0;
}
.all {
width: 500px;
height: 200px;
padding: 7px;
border: 1px solid #ccc;
margin: 100px auto;
position: relative;
}
.screen {
width: 500px;
height: 200px;
overflow: hidden;
position: relative;
}
.screen li {
width: 500px;
height: 200px;
overflow: hidden;
float: left;
}
.screen ul {
position: absolute;
left: 0;
top: 0px;
width: 3000px;
}
.all ol {
position: absolute;
right: 10px;
bottom: 10px;
line-height: 20px;
text-align: center;
}
.all ol li {
float: left;
width: 20px;
height: 20px;
background: #fff;
border: 1px solid #ccc;
margin-left: 10px;
cursor: pointer;
}
.all ol li.current {
background: #DB192A;
}
#arr {
display: none;
}
#arr span {
width: 40px;
height: 40px;
position: absolute;
left: 5px;
top: 50%;
margin-top: -20px;
background: #000;
cursor: pointer;
line-height: 40px;
text-align: center;
font-weight: bold;
font-family: '黑体';
font-size: 30px;
color: #fff;
opacity: 0.3;
border: 1px solid #fff;
}
#arr #right {
right: 5px;
left: auto;
}
</style>
</head>
<body>
<div class="all" id='box'>
<div class="screen"><!--相框-->
<ul>
<li><img src="images/1.jpg" width="500" height="200"/></li>
<li><img src="images/2.jpg" width="500" height="200"/></li>
<li><img src="images/3.jpg" width="500" height="200"/></li>
<li><img src="images/4.jpg" width="500" height="200"/></li>
<li><img src="images/5.jpg" width="500" height="200"/></li>
</ul>
<ol>
</ol>
</div>
<div id="arr"><span id="left"><</span><span id="right">></span></div>
</div>
<script>
//根据id获取元素对象
function my$(id) {
return document.getElementById(id);
}
//首先获取所有需要的元素
//最外层的box对象
let box = my$("box");
//相册screen对象
let screen = box.children[0];
//相册宽度
let imgWidth = screen.offsetWidth;
//ul对象--移动的对象
let ulObj = screen.children[0];
//ul下面的li
let list = ulObj.children;
//ol对象
let olObj = screen.children[1];
//arr对象 控制鼠标移上显示鼠标移出隐藏
let arrObj = my$("arr");
//首先遍历大的图片li生成ol里面的按钮li ---先写最容易控制的右下角按钮点击显示对应图片
for (let i = 0; i < list.length; i++) {
//创建ol中的li元素并添加内容
let liObj = document.createElement("li");
liObj.innerHTML = (i + 1);
olObj.appendChild(liObj);
//为移动ul做准备,需要给每个li一个索引值
liObj.setAttribute("index", i);
//鼠标移上事件
liObj.onmouseover = mouseoverHandle;
}
let imgIndex = 0;
//鼠标移上右下角按钮的事件处理函数
function mouseoverHandle() {
//第一 鼠标移上显示红色背景
//排它-取消所有ol下li的class
for (let j = 0; j < olObj.children.length; j++) {
olObj.children[j].removeAttribute("class");
}
//给当前元素设置背景class
this.setAttribute("class", "current");
//第二 鼠标移上移动显示到对应索引的图片
imgIndex = this.getAttribute("index");
animate(ulObj, -imgIndex * imgWidth);
}
//默认给第一个点击按钮设置背景色
olObj.children[0].setAttribute("class", "current")
//深拷贝第一张图片放在ul中的最后,变成原来的length+1 以备自动播放时无缝衔接
ulObj.appendChild(list[0].cloneNode(true));
//此时比原先的图片要多一张
//自动播放效果在做完点击右侧按钮的事件之后再来写,
//本质其实就是调用点击右侧的事件函数,定时跑这个函数
let autoId = setInterval(clickRight, 1500);
//鼠标移上box显示左右两个焦点按钮
box.onmouseover = function () {
//鼠标移上显示
arrObj.style.display = "block";
//清除定时器自动播放
clearInterval(autoId);
}
box.onmouseout = function () {
// 鼠标移开取消显示
arrObj.style.display = "none";
//开启自动播放定时器
autoId = setInterval(clickRight, 2000);
}
//点击左按钮的事件
my$("left").onclick = function () {
// 写完右侧的再来写左侧
if (imgIndex == 0) {
ulObj.style.left = -(ulObj.children.length - 1) * imgWidth;
imgIndex = ulObj.children.length - 1;
}
// 首先是切换图片 --需要和上面的鼠标移上右下侧按钮显示的一致,一次上面的index值需要公用
//点击时索引+1
imgIndex--;
animate(ulObj, -imgIndex * imgWidth);
//这个时候测试会发现在使用右击按钮滚动图片时,右下角的按钮背景没有随之改变,因此这里也需要做处理
//直接做排它
for (let j = 0; j < olObj.children.length; j++) {
olObj.children[j].removeAttribute("class");
}
//设置当前索引的颜色
olObj.children[imgIndex].setAttribute("class", "current");
}
//点击右按钮的事件
my$("right").onclick = clickRight;
function clickRight() {
//因为此时的最后一张图片 和第一张是同一张,需要做处理,在索引值到最后一个时,立马设置为第一张的索引,并跳回第一张
if (imgIndex == ulObj.children.length - 1) {
ulObj.style.left = 0;
imgIndex = 0;
}
// 首先是切换图片 --需要和上面的鼠标移上右下侧按钮显示的一致,一次上面的index值需要公用
//点击时索引+1
imgIndex++;
animate(ulObj, -imgIndex * imgWidth);
//这个时候测试会发现在使用右击按钮滚动图片时,右下角的按钮背景没有随之改变,因此这里也需要做处理
if (imgIndex == ulObj.children.length - 1) {
//最后一张的特殊性做判断
//即在显示最后一张图片时,右下角的标识应该显示第一个背景颜色
olObj.children[0].setAttribute("class", "current");
//同时取消最后的颜色
olObj.children[olObj.children.length - 1].removeAttribute("class");
} else {
//设置当前索引的颜色
olObj.children[imgIndex].setAttribute("class", "current");
//取消上一个的颜色
olObj.children[imgIndex].previousElementSibling.removeAttribute("class");
}
}
//复习公共方法--给任意元素移动到指定目标位置
function animate(element, target) {
clearInterval(element.timerId);
element.timerId = setInterval(function () {
//首先获取当前元素的left值
let current = element.offsetLeft;
//设置步数,判断当前值和目标值的大小,区分正负,即从左向右走,还是从右向左走
let step = 20;
step = current < target ? step : -step;
current += step;
if (Math.abs(target - current) > Math.abs(step)) {
element.style.left = current + "px";
} else {
clearInterval(element.timerId);
element.style.left = target + "px";
}
}, 10)
}
</script>
</body>
</html>
4.移动端轮播图(仿的老jd页面,包含自动轮播,手指滑动切换图片,指示器随着图片变化而变化,用过渡动画,不用自己手写动画)
- 轮播图的实现:
- 1.自动轮播 需要定时器+过渡效果
- 2.底部圆点随着图片轮播时发生改变 需要根据索引做切换
- 3.滑动效果 需要触摸事件
- 4.滑动结束时 如果滑动的距离小于屏幕的1/2 吸附回去 过渡
- 5.滑动结束时 如果滑动的距离大于屏幕的1/2 切换图片(上一张/下一张) 根据滑动的方向决定 过渡效果
<div class="jd_banner">
<ul>
<!--无缝衔接-->
<li><a href="#"><img src="images/l8.jpg" alt=""></a></li>
<li><a href="#"><img src="images/l1.jpg" alt=""></a></li>
<li><a href="#"><img src="images/l2.jpg" alt=""></a></li>
<li><a href="#"><img src="images/l3.jpg" alt=""></a></li>
<li><a href="#"><img src="images/l4.jpg" alt=""></a></li>
<li><a href="#"><img src="images/l5.jpg" alt=""></a></li>
<li><a href="#"><img src="images/l6.jpg" alt=""></a></li>
<li><a href="#"><img src="images/l7.jpg" alt=""></a></li>
<li><a href="#"><img src="images/l8.jpg" alt=""></a></li>
<li><a href="#"><img src="images/l1.jpg" alt=""></a></li>
</ul>
<ul>
<li class="now"><a href=""></a></li>
<li><a href=""></a></li>
<li><a href=""></a></li>
<li><a href=""></a></li>
<li><a href=""></a></li>
<li><a href=""></a></li>
<li><a href=""></a></li>
<li><a href=""></a></li>
</ul>
</div>
//面向对象 构造函数的方式
let bannerScroll = function () {
let Banner = function (bannerObj) {
this.bannerBox = bannerObj || document.querySelector(".jd_banner");
this.bannerWidth = this.bannerBox.offsetWidth;
this.imageBox = this.bannerBox.querySelector("ul:first-child");
this.pointBox = this.bannerBox.querySelector("ul:last-child");
this.points = this.pointBox.querySelectorAll("li");
this.index = 1;
}
Banner.prototype.init = function () {
this.autoScroll();
this.touchScroll();
};
//1.自动滚动
Banner.prototype.autoScroll = function () {
let _this = this;
//定时器
this.timer = setInterval(function () {
_this.index++;
_this.addTransition();
_this.setTranslateX((-_this.index) * _this.bannerWidth);
}, 2000);
_this.imageBox.addEventListener("transitionend", function () {
if (_this.index >= 9) {
_this.index = 1;
_this.removeTransition();
_this.setTranslateX((-_this.index) * _this.bannerWidth);
} else if (_this.index <= 0) {
_this.index = 8;
_this.removeTransition();
_this.setTranslateX((-_this.index) * _this.bannerWidth);
}
//小圆点同步
_this.syncPoints();
});
};
//2.小圆点同步
Banner.prototype.syncPoints = function () {
for (let i = 0; i < this.points.length; i++) {
this.points[i].classList.remove("now");
}
this.points[this.index - 1].classList.add("now");
};
//3.手指滑动事件
Banner.prototype.touchScroll = function () {
this.bannerBox.addEventListener("touchstart", evt => {
console.log("start");
clearInterval(this.timer);
this.moveX0 = evt.targetTouches[0].clientX;
});
this.bannerBox.addEventListener("touchmove", evt => {
console.log("move");
this.moveFlag = true;
let moveX1 = evt.targetTouches[0].clientX;
this.moveWidth = moveX1 - this.moveX0;
this.removeTransition();
this.setTranslateX((-this.index) * this.bannerWidth + this.moveWidth);
});
this.bannerBox.addEventListener("touchend", evt => {
console.log("end");
if (this.moveFlag) {
if (Math.abs(this.moveWidth) <= this.bannerWidth / 2) {
this.addTransition();
this.setTranslateX((-this.index) * this.bannerWidth);
} else {
this.moveWidth > 0 ? this.index-- : this.index++;
this.addTransition();
this.setTranslateX((-this.index) * this.bannerWidth);
}
}
this.moveX0 = 0;
this.moveWidth = 0;
let _this = this;
this.timer = setInterval(function () {
_this.index++;
_this.addTransition();
_this.setTranslateX((-_this.index) * _this.bannerWidth);
}, 2000)
});
};
//添加过渡
Banner.prototype.addTransition = function () {
this.imageBox.style.transition = "all 0.3s";
this.imageBox.style.webkitTransition = "all 0.3s";
};
//取消过渡
Banner.prototype.removeTransition = function () {
this.imageBox.style.transition = "none";
this.imageBox.style.webkitTransition = "none";
};
//位移
Banner.prototype.setTranslateX = function (width) {
this.imageBox.style.transform = "translateX(" + width + "px)";
this.imageBox.style.webkitTransform = "translateX(" + width + "px)";
};
let banner = new Banner();
banner.init();
};