最近在研究手机端页面,其中有个简单的图片滑动效果,折腾了半天,于是我写了个小的demo,在此分享一下。
大概功能:自定义是否切换,支持滑动切换,循环切换等等,具体可以拿demo代码自己本地试试
大概思路:把当前张显示,上一张定位在最前面,下一张定义在最后面,其他隐藏,通过touchstart、touchmove、touchend 三个事件加上css3的transition变
化效果配合,实现滑动切换图片,效果类似于手机版京东的banner
开发是基于Zepto框架,当然也支持其他任何一款手机端框架,只需将代码中的美元符号$换为指定框架操作符即可。
下面是该效果的源码,明白思路的朋友可以自己封装成小插件 注意:只支持手机端哦
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width; initial-scale=1.0;" />
<title>Document</title>
<style>
*{margin:0;padding:0;}
.slider_wrap{position:relative;height:168px;overflow:hidden;}
.slider_wrap .slider_content{height:100%;position:absolute;top:0;left:0;}
.slider_wrap .slider_item{height:100%;position:absolute;top:0;left:0;}
.slider_wrap .slider_item img{border:0;width:100%;height:100%;}
.slider_wrap .slider_btn{width:100%;height:10px;position:absolute;bottom:10px;left:0;text-align:center;}
.slider_wrap .slider_btnlist{width:6px;height:6px;border:1px solid rgba(255,255,255,.8);display:inline-block;border-radius:50%;margin:5px;}
.slider_wrap .slider_btnlist.curr{background:rgba(255,255,255,.8);}
</style>
</head>
<script src="http://zeptojs.com/zepto.min.js"></script>
<script>
$(document).ready(function(){
// 默认设置
var setting = {
'index':0,
'duration':300,
'interval':3000,
'autoPlay':false,
'timingFn':'ease'
}
//节点获取
var selector = {
'sliderWrap':'.slider_wrap',
'sliderCont':'.slider_content',
'sliderItem':'.slider_item',
'sliderBtn':'.slider_btn',
'sliderBtnList':'.slider_btnlist',
'showBtnList':'.curr'
}
//用于记录触屏的坐标以及触屏的时间
var touchRecord = {'startX':'','startT':'','endX':'','endT':'','changeX':'','changeT':''}
var sliderWrap = $(selector.sliderWrap);
var sliderCont = sliderWrap.find(selector.sliderCont);
var sliderItem = sliderWrap.find(selector.sliderItem);
var sliderBtn = sliderWrap.find(selector.sliderBtn);
var sliderBtnList = sliderWrap.find(selector.sliderBtnList);
var timer = null;
var sliderWidth = $(window).width();
var sliderLength= sliderItem.length;
initStyle();
createBtn();
addEvent();
//初始化样式
function initStyle(){
sliderWidth = $(window).width();
sliderWrap.css('width',sliderWidth);
sliderCont.css('width',sliderWidth);
sliderItem.css('width',sliderWidth);
transitionFn(setting.duration,0);
}
// 创建索引按钮
function createBtn(){
var BtnList = '';
sliderItem.each(function(){
BtnList += "<div class="+selector.sliderBtnList.slice(1)+"></div>";
});
var Btn = "<div class="+selector.sliderBtn.slice(1)+">"+BtnList+"</div>";
sliderWrap.append(Btn);
sliderBtn = sliderWrap.find(selector.sliderBtn);
sliderBtnList = sliderWrap.find(selector.sliderBtnList);
showBtnList();
}
// 当前按钮高亮显示
function showBtnList(){
var showBtnList = selector.showBtnList.slice(1);
sliderBtnList.eq(setting.index).addClass(showBtnList).siblings().removeClass(showBtnList);
}
// 设置过渡函数
function transitionFn(duration,changeX){
// 索引处理,如果小于0则返回最大值 反之
if(setting.index < 0) setting.index = sliderLength-1;
if(setting.index > sliderLength-1) setting.index = 0;
// 保存当前显示张,下一张,上一张
var currItem = sliderItem.eq(setting.index);
var prevItem = sliderItem.eq(setting.index-1);
var nextItem = sliderItem.eq(setting.index+1);
// 如果当前张为第一张,则下一张为最后张 反之
if(setting.index-1 < 0) prevItem = sliderItem.eq(sliderLength-1);
if(setting.index+1 > sliderLength-1) nextItem = sliderItem.eq(0);
sliderItem.css({
'left':0,
'z-index':-2,
'transition':duration+'ms '+setting.timingFn,
'-webkit-transition':duration+'ms '+setting.timingFn
});
currItem.css({
'left':changeX,
'z-index':0
});
prevItem.css({
'left':-sliderWidth+changeX,
'z-index':-1
});
nextItem.css({
'left':sliderWidth+changeX,
'z-index':-1
});
showBtnList();
}
// 触屏开始
function touchStartFn(e){
var e = e || window.event;
e.preventDefault();
var touch = e.targetTouches[0];
//记录手指触屏的X坐标以及当前时间
touchRecord.startX = touch.pageX;
touchRecord.startT = new Date().getTime();
transitionFn(0,0);
clearIntervalFn();
}
function touchMoveFn(e){
var e = e || window.event;
e.preventDefault();
var touch = e.targetTouches[0];
//记录滑动过程中的X坐标并计算滑动过程中改变的X坐标
touchRecord.endX = touch.pageX;
touchRecord.changeX = touchRecord.endX-touchRecord.startX;
transitionFn(0,touchRecord.changeX);
}
function touchEndFn(e){
var e = e || window.event;
e.preventDefault();
var touch = e.targetTouches[0];
//记录滑动结束的时间并计算滑动整个过程持续的时间
touchRecord.endT = new Date().getTime();
touchRecord.changeT = touchRecord.endT-touchRecord.startT;
// 如果不是触屏(改变的时间大于50)并且滑动持续的时间大于300毫秒 或者 滑动改变的位移大于需要过渡宽度的一半 则返回ture
var onNext = Boolean( (touchRecord.changeT>50 && touchRecord.changeT<300) || Math.abs(touchRecord.changeX)>=sliderWidth/2 );
// 当手指左往右滑 即改变大于0 并且满足进行下一张的条件
if(touchRecord.changeX > 0 && onNext){
setting.index--;
}else if(touchRecord.changeX < 0 && onNext){
setting.index++;
}
transitionFn(setting.duration,0);
// 过渡完成清除计时器,并且重置坐标记录
setIntervalFn();
touchRecord = {'startX':'','startT':'','endX':'','endT':'','changeX':'','changeT':''}
}
//绑定事件
function addEvent(){
sliderWrap.bind({
'touchstart':function(){touchStartFn()},
'touchmove':function(){touchMoveFn()},
'touchend':function(){touchEndFn()}
});
$(window).resize(function(){
initStyle()
});
setIntervalFn();
}
//开启计时器
function setIntervalFn(){
clearIntervalFn();
if(setting.autoPlay){
timer = setInterval(function(){
setting.index++;
transitionFn(setting.duration,0);
},setting.interval);
}
}
//关闭计时器
function clearIntervalFn(){
clearInterval(timer);
}
});
</script>
<body>
<div class="slider_wrap">
<div class="slider_content">
<div class="slider_item">
<img src="https://m.360buyimg.com/mobilecms/s720x322_jfs/t4048/197/859073037/171484/90a15e9b/5861db95N427b7cae.jpg!q70.jpg" alt="">
</div>
<div class="slider_item">
<img src="https://img1.360buyimg.com/da/jfs/t3952/16/1004078680/129059/c89f73f5/5864dd5bN23b1e0be.jpg" alt="">
</div>
<div class="slider_item">
<img src="https://img1.360buyimg.com/da/jfs/t3811/70/2677776384/54829/30bd0b0/5864b41bN178351ee.jpg" alt="">
</div>
<div class="slider_item">
<img src="https://m.360buyimg.com/mobilecms/s720x322_jfs/t3097/65/5212474230/112193/39bc6ac5/5865d793Nc7173737.jpg!q70.jpg" alt="">
</div>
<div class="slider_item">
<img src="https://img1.360buyimg.com/da/jfs/t3169/220/4367992935/58978/501d5b74/58401652N332c289f.jpg" alt="">
</div>
</div>
</div>
</body>
</html>