踏着荆棘,也不觉悲苦;有泪可落,亦不是悲凉。
封装一个移动端的轮播图,移动端的轮播图呢!和pc端还不一样,事件不一样,触发的条件也不一样,所以今天来封装一个基本的轮播图.
想必大家也都知道,移动端嘛,屏幕都是不一样大的,屏幕的大小取决于制造商,所以,这样咱们使用流动式布局,可以吧!!
第一步,HTML基本样式
首先,咱先先出基本的轮播图样式,
<div class="container">
<ul>
<li>
<img src="images/l1.jpg">
</li>
<li>
<img src="images/l2.jpg">
</li>
<li>
<img src="images/l3.jpg">
</li>
<li>
<img src="images/l4.jpg">
</li>
</ul>
</div>
这个样式没有问题把,一个大盒子包裹着需要运动的ul, container作为运动视口, ul 作为运动的盒子,这要是还有问题的话,不妨回去学学HTML… 好了,接下来写css.
第二部,参数三样式
body {
margin: 0;
}
.container {
width: 100%;
/* 当子元素不缩放的时候,将会占4个屏幕的宽度,所以需要溢出影藏 */
overflow: hidden;
}
.container ul {
list-style: none;
margin: 0;
padding: 0;
/* 子元素需要运用flex,故将父元素设为flex布局 */
display: flex;
}
.container ul li {
/*因为父盒子设为flex布局,所有的图片都会在一排缩放进行显示,所以将它们设置为不缩放*/
flex-shrink: 0;
width: 100%;
}
.container img {
vertical-align: top;
width: 100%;
}
样式已经写出来了,咱们接下来写js , js里面运用到了一个函数,就是左滑,右划的函数,这里不做太多解释 , 我的博客里面有这个函数的封装 ,
这里进行思路分析,对照着代码分析 :
1. 首先获取到大盒子,在获取到其子元素,也就是视口
2.这里介绍一个方法,可以获取到元素宽度的一个方法document.documentElement.clientWidth;
3. 设置一个变量,相当于轮播图的索引,
4. 滑动的距离设置为全局变量
首先必须触发滑动事件 , 这里就得计算出当前的位置,因为要使用该参数来进行判断,当图片可以拖动了,但是问题出现了,当我下一次点击了时候,又回到了起始位置,所以咱们得使用之前位置加上当前滑动的距离,才可以避免这个问题,接下来使用左滑与右划事件,这里不做太多介绍,因为没有什么技术难度… 当左滑与右划实现之后,新的问题出现了,也就是动画队列,当我快速的滑动的时候,图片不会流畅的被拖动,所以需要清除动画,故为 scrollContainer.style.transition = ‘none’;
<script type="text/javascript">
//轮播图的当前位置 -index * 一张图片的宽度
var container = document.querySelector('.container');
var scrollContainer = container.children[0];
// 屏幕的宽度
var sw = document.documentElement.clientWidth;
// 轮播图的索引
var index = 0;
// 滑动距离
var distance = 0;
swipe(container, {
swipeLeft: function() {
// 如果当前的滑动距离超过了屏幕宽度的一半 让他滑动到下一张
if (Math.abs(distance) > sw / 2) {
if (index < 3) {
index++;
}
}
// 为滑动添加过渡动画
scrollContainer.style.transition = 'transform .6s';
// 让ul滚动
scrollContainer.style.transform = 'translateX(' + -index * sw + 'px)';
},
swipeRight: function() {
// 如果当前的滑动距离超过了屏幕宽度的一半 让他滑动到下一张
if (Math.abs(distance) > sw / 2) {
if (index > 0) {
index--;
}
}
// 为滑动添加过渡动画
scrollContainer.style.transition = 'transform .6s';
// 让ul滚动
scrollContainer.style.transform = 'translateX(' + -index * sw + 'px)';
},
drag: function(e) {
// 滑动距离 e.touches[0].pageX实际上就是moveX
distance = e.touches[0].pageX - e.info.startX;
// 轮播图的当前位置加上滚动距离
var current = -index * sw + distance;
// 在手指拖动轮播图的时候禁止过渡动画
scrollContainer.style.transition = 'none';
scrollContainer.style.transform = 'translateX(' + current + 'px)';
}
});
// 下面为封装好的手势函数
function swipe(el, options) {
var startX = 0;
var startY = 0;
var moveX = 0;
var moveY = 0;
var disX = 0;
var disY = 0;
// 没有发生touchmove事件
var isMove = false;
// 默认值
var defaults = {
swipeLeft: function() {},
swipeRight: function() {},
swipeDown: function() {},
swipeUp: function() {},
drag: function() {}
}
// 如果用户传参了 就用用户传的 如果没传 就用默认值
// for (var attr in options) {
// defaults[attr] = options[attr];
// }
// 对象覆盖 用第二个参数对象覆盖第一个参数对象 且覆盖结果会影响到原对象
Object.assign(defaults, options);
// 记录开始滑动的坐标
el.addEventListener('touchstart', function(e) {
startX = e.touches[0].pageX;
startY = e.touches[0].pageY;
disX = startX - el.offsetLeft;
disY = startY - el.offsetTop;
});
// 记录滑动过程中的坐标
el.addEventListener('touchmove', function(e) {
moveX = e.touches[0].pageX;
moveY = e.touches[0].pageY;
isMove = true;
// 将touchstart事件发生时侯的x和y保存到当前的事件对象中
e.info = {
startX: startX,
startY: startY,
disX: disX,
disY: disY
}
// 将在touchmove事件发生的时候要做的事情写在函数外面 => drag
defaults.drag.call(el, e);
});
// 判断垂直滑动还是水平滑动 ...
el.addEventListener('touchend', function(e) {
// 如果发生了滑动事件
if (isMove) {
// 水平边长
var absX = Math.abs(moveX - startX);
// 垂直边长
var absY = Math.abs(moveY - startY);
if (absX > absY) {
// 水平
// console.log('水平');
if (moveX - startX > 0) {
// console.log('向右滑动');
defaults.swipeRight.call(el, e);
} else {
//console.log('向左滑动');
defaults.swipeLeft.call(el, e);
}
} else {
// 垂直
// console.log('垂直');
if (moveY - startY > 0) {
// console.log('向下滑动');
defaults.swipeDown.call(el, e);
} else {
// console.log('向上滑动');
defaults.swipeUp.call(el, e);
}
}
}
// 初始isMove变量方便 下回触发事件的时候做判断
isMove = false;
});
}
</script>
在此附上我的QQ: 2489757828 有问题的话可以一同探讨
我的私人博客: 李大玄