首先我们看看效果如下:
通过左右箭头可以选择一个特定的发货地址,我们可以看看dom结构:
其中Q_location是我们的包裹容器,通过它设置元素的大小,hwslide就是我们自己实例化的对象(但是必须在dom都插入完成后才能实例化),其宽度和高度都设置为100%就可以了。
第一步:我们可以看到方法其实是在每一个zepto实例上的
$.fn.hwSlider = function(options) {
//this为zepto对象
var hwSlider = new HwSlider(this, options);
//逐个元素调用init方法,init中的this是我们的HwSlider对象
return this.each(function () {
hwSlider.init();
});
};
注意:
我们必须在所有的DOM都构建完毕后才能实例化我们的HwSlide对象,否则可能存在元素高度没有计算完成的情况。
第二步:我们看看实例化对象时候的options对象
var HwSlider = function(ele, opt){
var self = this;
self.$element = ele,
self.defaults = {
width: 480, //初始宽度
height: 110, //初始高度
start: 1, //初始滑动位置,从第几个开始滑动
interval: 3000, //间隔时间,单位ms
autoPlay: false, //是否自动滑动
//length表示滑块的个数,在后面代码中设置
dotShow: false, //是否显示圆点导航
arrShow: true, //是否显示左右方向箭头导航
touch: true,//是否支持触摸滑动
start:1//配置显示第一个,也就是下标是0的元素(这里表示是第几个,从1开始编号)
},
self.options = $.extend({}, self.defaults, opt)
}
注意:上面的defaults对象都已经注明了
第三步:我们看看init中做了什么处理
HwSlider.prototype = {
init: function(){
var self = this,
ele = self.$element;
var sliderInder = ele.children('ul')
var hwsliderLi = sliderInder.children('li');
//每一个li就是一个滑块
var hwsliderSize = hwsliderLi.length; //滑块的总个数
self.options.length=hwsliderSize;//把滑块的个数放在options中
//配置的start表示我们的index
var index = self.options.start;
var touchStartY = 0,touchStartX = 0;
//指定显示index配置的滑块显示
for(var i=1;i<=hwsliderSize;i++){
if(index==i) {
hwsliderLi.eq(index-1).css('display','block');
}
}
//显示左右方向键,我们传入的elem表示的是id为hwslider的元素
if(self.options.arrShow){
var arrElement = '<a href="javascript:;" id="pre" class="arr prev"><</a><a href="javascript:;" id="next" class="arr next">></a>';
ele.append(arrElement);
}
//显示圆点导航
if(self.options.dotShow){
var dot = '';
for(i=1;i<=hwsliderSize;i++){
if(index==i){
dot += '<span data-index="'+i+'" class="active"></span>';
}else{
dot += '<span data-index="'+i+'"></span>';
}
}
var dotElement = '<div class="dots">'+dot+'</div>';
ele.append(dotElement);
}
//窗口大小发生变化的时候
var load = function(){
var sWidth = ele.width();
//根据滑块宽度等比例缩放高度,也就是说保持宽高比不变
var sHeight = self.options.height;
ele.css('height',sHeight);
//设置箭头元素的显示top/left的值,其中sHeight表示元素的hwslider高度,40表示
if(self.options.arrShow){
console.log('sHeight=',sHeight);
var arrOffset = (sHeight-40)/2;
ele.find(".arr").css('top',arrOffset/75+'rem'); //导航箭头位置
}
//是否显示当前显示的元素
if(self.options.dotShow){
var dotWidth = hwsliderSize*20;
var dotOffset = (sWidth-dotWidth)/2;
ele.find(".dots").css('left',dotOffset/75+'rem'); //导航圆点位置
}
}
ele.css('height',self.options.height);
//页面onload时候设置滑块的left/top,其实我们建议使用css来设置rem值来完成,而不用js控制
load();
//点击导航圆点
if(self.options.dotShow){
ele.find(".dots span").on('click', function(event) {
event.preventDefault();
if(self.clickable){
var dotIndex = $(this).data('index');
if(dotIndex > index){
dir = 'next';
}else{
dir = 'prev';
}
if(dotIndex != index){
index = dotIndex;
self.moveTo(index, dir);
}
}
});
}
//绑定箭头事件,点击可以是循环的地址展示
if(self.options.arrShow){
ele.find('.next').on('click', function(event) {
event.preventDefault();
if(index >= hwsliderSize){
// index = 1;
//通过设置为1,我们可以循环的,此处不要求循环
index=self.options.length;
}else{
index += 1;
}
//调用moveTo方法
self.moveTo(index,'next');
});
//点击左箭头
ele.find(".prev").on('click', function(event) {
event.preventDefault();
if(index == 1){
index = hwsliderSize;
}else{
index -= 1;
}
self.moveTo(index,'prev');
});
}
//自动滑动
if(self.options.autoPlay){
var timer;
var play = function(){
index++;
if(index > hwsliderSize){
index = 1;
}
self.moveTo(index, 'next');
}
timer = setInterval(play, self.options.interval); //设置定时器
};
//触摸滑动
if(self.options.touch){
hwsliderLi.on({
//触控开始
'touchstart': function(e) {
touchStartY = e.touches[0].clientY;
touchStartX = e.touches[0].clientX;
},
//触控结束
'touchend': function(e) {
var touchEndY = e.changedTouches[0].clientY,
touchEndX = e.changedTouches[0].clientX,
yDiff = touchStartY - touchEndY,
xDiff = touchStartX - touchEndX;
//判断滑动方向
if ( Math.abs( xDiff ) > Math.abs( yDiff ) ) {
//水平方向的滑动
if ( xDiff > 5 ) {
//对于tap事件,我们也是不允许循环显示的
if(index >= hwsliderSize){
// index = 1;
index=hwsliderSize;
}else{
index += 1;
}
self.moveTo(index,'next');
} else {
if(index == 1){
// index = hwsliderSize;
index=1;
}else{
index -= 1;
}
self.moveTo(index,'prev');
}
}
touchStartY = null;
touchStartX = null;
},
//触控移动
'touchmove': function(e) {
if(e.preventDefault) { e.preventDefault(); }
}
});
}
},
//滑动移动
moveTo: function(index,dir){
var self = this,
ele = self.$element;
var dots = ele.find(".dots span");
var sliderInder = ele.children('ul');
var hwsliderLi = sliderInder.children('li');
//控制pre和next的隐藏
var pre=document.getElementById('pre');
var next=document.getElementById('next');
//往左边的显示出来
index==1?pre.style.display='none':pre.style.display="block";
//已经到达最后,我们
index==self.options.length?next.style.display="none":next.style.display='block';
if(dir == 'next'){
//当前滑块动画
hwsliderLi.removeAttr('class').css('display','none');
// hwsliderLi.removeAttr('class').css('display','block');
hwsliderLi.eq(index-2).addClass('moveout_right').css('display','block');
//下一个滑块动画
hwsliderLi.removeClass('active').eq(index-1).addClass('movein_right').css('display','block');
}else{
//当前滑块动画
hwsliderLi.removeAttr('class').css('display','none');
// hwsliderLi.removeAttr('class').css('display','block');
hwsliderLi.eq(index-3).addClass('moveout_left').css('display','block');
//下一个滑块动画
hwsliderLi.removeClass('active').eq(index-1).addClass('movein_left').css('display','block');
}
//self.clickable = true;
//显示可切换的圆点
dots.removeClass('active');
dots.eq(index-1).addClass('active');
}
}
注意:我们很显然可以看到其原理和我们见到的滑动门效果是一样的,在此不多说,我们看看其中的touch事件:
if(self.options.touch){
hwsliderLi.on({
//触控开始
'touchstart': function(e) {
touchStartY = e.touches[0].clientY;
touchStartX = e.touches[0].clientX;
},
//触控结束
'touchend': function(e) {
var touchEndY = e.changedTouches[0].clientY,
touchEndX = e.changedTouches[0].clientX,
yDiff = touchStartY - touchEndY,
xDiff = touchStartX - touchEndX;
//判断滑动方向
if ( Math.abs( xDiff ) > Math.abs( yDiff ) ) {
//水平方向的滑动
if ( xDiff > 5 ) {
//对于tap事件,我们也是不允许循环显示的
if(index >= hwsliderSize){
// index = 1;
index=hwsliderSize;
}else{
index += 1;
}
self.moveTo(index,'next');
} else {
if(index == 1){
// index = hwsliderSize;
index=1;
}else{
index -= 1;
}
self.moveTo(index,'prev');
}
}
touchStartY = null;
touchStartX = null;
},
//触控移动
'touchmove': function(e) {
if(e.preventDefault) { e.preventDefault(); }
}
});
}
}
注意:在touchstart中我们获取
touches列表,但是在touchend中我们获取
changedTouches集合,然后计算触点的变换的距离。
最后:我们看看如何实例化
AddressListsDOM=`<span class='Q_close'></span>
<span class='Q_taokl'></span>
<p class='Q_description'>奖品标题文案奖品标题文案奖品标题文案奖品将寄送到以下地址,请选择确认</p>
<div class='Q_locations'>
<div id="hwslider" class="hwslider">
<ul>${AddressListsDOM} </ul>
</div> </div>
<span class='Q_max-button'>确定</span>
<p class="Q_warning">重要说明:<br>实物奖品寄送周期为15个工作日,请耐心等待哦!</p>`;
let QPopupMax=document.querySelector('#Q_popup_max');
QPopupMax.style.display='block';
QPopupMax.innerHTML=AddressListsDOM;
QMask.style.display='block';
//不是location调用的
$("#hwslider").hwSlider({
autoPlay: false,
dotShow: false,
touch: true
});
注意:是在dom都已经插入的时候才能调用hwSlide方法。