islider.js轮播图
阅读原文时间:2023年07月09日阅读:3

本篇文章地址:https://www.cnblogs.com/Thehorse/p/11601032.html

css

#iSlider-effect-wrapper {
height: 220px;
width: 100%;
margin: 0 auto;
margin-top: 0.2rem;
overflow: hidden;
position: relative;
}
.iSlider-effect ul{
list-style: none;
padding: 0;
margin: 0;
height: 205%;
overflow: hidden
}
.iSlider-effect li {
position: absolute;
margin: 0;
padding: 0;
height: 100%;
overflow: hidden;
display: -webkit-box;
-webkit-box-pack: center;
-webkit-box-align: center;
list-style: none
}

js

/**
* iSlider
* A simple, efficent mobile slider
* @Author BEFE
*
* @param {Object} opts 参数集
* @param {Element} opts.dom 外层元素 Outer wrapper
* @param {Object} opts.data 数据列表 Content data
* Please refer to README 请参考README
* @class
*/

'use strict';

var iSlider = function (opts) {
if (!opts.dom) {
throw new Error('dom element can not be empty!');
}

if (!opts.data || !opts.data.length) {
throw new Error('data must be an array and must have more than one element!');
}

this._opts = opts;
this._setting();
this._renderHTML();
this._bindHandler();
};

// setting parameters for slider
iSlider.prototype._setting = function () {
var opts = this._opts;

// dom element wrapping content
this.wrap = opts.dom;
// your data
this.data = opts.data;
// default type
this.type = opts.type || 'pic';
// default slide direction
this.isVertical = opts.isVertical || false;
// Overspread mode
this.isOverspread = opts.isOverspread || false;
// Play time gap
this.duration = opts.duration || 2000;
// start from 0
this.slideIndex = this.slideIndex || 0;
this.dotOutside = opts.dotOutside || 0;
this.axis = this.isVertical ? 'Y' : 'X';
this.width = this.wrap.clientWidth;
this.height = this.wrap.clientHeight;
this.ratio = this.height / this.width;
this.scale = opts.isVertical ? this.height : this.width;

this.useTime=opts.useTime;

// Callback function when your finger is moving
this.onslide = opts.onslide;
// Callback function when your finger touch the screen
this.onslidestart = opts.onslidestart;
// Callback function when the finger move out of the screen
this.onslideend = opts.onslideend;
// Callback function when the finger move out of the screen
this.onslidechange = opts.onslidechange;

this.dotChange=null;

// looping logic adjust
if (this.data.length < 2) {
this.isLooping = false;
this.isAutoPlay = false;
} else {
this.isLooping = opts.isLooping || false;
this.isAutoplay = opts.isAutoplay || false;
}

// little trick set, when you chooce tear & vertical same time
// iSlider overspread mode will be set true autometicly
if (opts.animateType === 'card' && this.isVertical) {
this.isOverspread = true;
}

// Autoplay mode
if (this.isAutoplay) {
this.play();
}

// debug mode
this.log = opts.isDebug ? function(str) {window.console.log(str);} : function() {};
// set Damping function
this._setUpDamping();
// stop autoplay when window blur
this._setPlayWhenFocus();
// set animate Function
this._animateFunc = (opts.animateType in this._animateFuncs)
? this._animateFuncs[opts.animateType]
: this._animateFuncs['default'];
};

// fixed bug for android device
iSlider.prototype._setPlayWhenFocus = function() {
var self = this;
window.addEventListener('focus', function() {
self.isAutoplay && self.play();
}, false);
window.addEventListener('blur', function() {
self.pause();
}, false);
};

/**
* animation parmas:
*
* @param {Element} dom 图片的外层

  • 容器 Img wrapper
    * @param {String} axis 动画方向 animate direction
    * @param {Number} scale 容器宽度 Outer wrapper
    * @param {Number} i
  • 容器index Img wrapper's index
    * @param {Number} offset 滑动距离 move distance
    */
    iSlider.prototype._animateFuncs = {

    'default': function (dom, axis, scale, i, offset) {
    dom.style.webkitTransform = 'translateZ(0) translate' + axis + '(' + (offset + scale * (i - 1)) + 'px)';
    console.log(axis, scale, i, offset)
    console.log(dom.style.webkitTransform)
    },

    'rotate': function (dom, axis, scale, i, offset) {
    var rotateDirect = (axis === 'X') ? 'Y' : 'X';
    var absoluteOffset = Math.abs(offset);
    var bdColor = window.getComputedStyle(this.wrap.parentNode, null).backgroundColor;

    if (this.isVertical) {
    offset = -offset;
    }

    this.wrap.style.webkitPerspective = scale * 4;

    if (i === 1) {
    dom.style.zIndex = scale - absoluteOffset;
    } else {
    dom.style.zIndex = (offset > 0) ? (1 - i) * absoluteOffset : (i - 1) * absoluteOffset;
    }

    dom.style.cssText += '-webkit-backface-visibility:hidden; -webkit-transform-style:preserve-3d; '
    + 'background-color:' + bdColor + '; position:absolute;';
    dom.style.webkitTransform = 'rotate' + rotateDirect + '(' + 90 * (offset / scale + i - 1) + 'deg) translateZ('
    + (0.888 * scale / 2) + 'px) scale(0.888)';
    },

    'flip': function (dom, axis, scale, i, offset) {
    var rotateDirect = (axis === 'X') ? 'Y' : 'X';
    var bdColor = window.getComputedStyle(this.wrap.parentNode, null).backgroundColor;
    if (this.isVertical) {
    offset = -offset;
    }
    this.wrap.style.webkitPerspective = scale * 4;

    if (offset > 0) {
    dom.style.visibility = (i > 1) ? 'hidden' : 'visible';
    } else {
    dom.style.visibility = (i < 1) ? 'hidden' : 'visible';
    }

    dom.style.cssText += 'position:absolute; -webkit-backface-visibility:hidden; background-color:' + bdColor + ';';
    dom.style.webkitTransform = 'translateZ(' + (scale / 2) + 'px) rotate' + rotateDirect
    + '(' + 180 * (offset / scale + i - 1) + 'deg) scale(0.875)';
    },

    'depth': function (dom, axis, scale, i, offset) {
    var zoomScale = (4 - Math.abs(i - 1)) * 0.18;
    this.wrap.style.webkitPerspective = scale * 4;
    dom.style.zIndex = (i === 1) ? 100 : (offset > 0) ? (1 - i) : (i - 1);
    dom.style.webkitTransform = 'scale(' + zoomScale + ', ' + zoomScale + ') translateZ(0) translate'
    + axis + '(' + (offset + 1.3 * scale * (i - 1)) + 'px)';
    },

    'flow': function (dom, axis, scale, i, offset) {
    var absoluteOffset = Math.abs(offset);
    var rotateDirect = (axis === 'X') ? 'Y' : 'X';
    var directAmend = (axis === 'X') ? 1 : -1;
    var offsetRatio = Math.abs(offset / scale);

    this.wrap.style.webkitPerspective = scale * 4;

    if (i === 1) {
    dom.style.zIndex = scale - absoluteOffset;
    } else {
    dom.style.zIndex = (offset > 0) ? (1 - i) * absoluteOffset : (i - 1) * absoluteOffset;
    }

    dom.style.webkitTransform = 'scale(0.7, 0.7) translateZ(' + (offsetRatio * 150 - 150) * Math.abs(i - 1) + 'px)'
    + 'translate' + axis + '(' + (offset + scale * (i - 1)) + 'px)'
    + 'rotate' + rotateDirect + '(' + directAmend * (30 - offsetRatio * 30) * (1 - i) + 'deg)';
    },

    'card': function (dom, axis, scale, i, offset) {
    var absoluteOffset = Math.abs(offset);

    if (i === 1) {
    dom.style.zIndex = scale - absoluteOffset;
    dom.cur = 1;
    } else {
    dom.style.zIndex = (offset > 0) ? (1 - i) * absoluteOffset * 1000 : (i - 1) * absoluteOffset * 1000;
    }

    if (dom.cur && dom.cur !== i) {
    setTimeout(function() {
    dom.cur = null;
    }, 300);
    }

    var zoomScale = (dom.cur) ? 1 - 0.2 * Math.abs(i - 1) - Math.abs(0.2 * offset / scale).toFixed(6) : 1;
    dom.style.webkitTransform = 'scale(' + zoomScale + ', ' + zoomScale + ') translateZ(0) translate' + axis
    + '(' + ((1 + Math.abs(i - 1) * 0.2) * offset + scale * (i - 1)) + 'px)';

    },
    'self' : function(dom,axis,scale,i,offset){
    var _scale= (i%2===0) ? _scale=Math.abs(offset/scale) : 1-Math.abs(offset/scale);
    dom.style.webkitTransform = 'translateZ(0) translate' + axis + '(' + (offset + scale * (i - 1)) + 'px) scale('+ _scale +')';
    }
    };
    /**
    * animation parmas:
    *
    * @param {Element} dom 图片的外层

  • 容器 Img wrapper
    * @param {String} axis 动画方向 animate direction
    * @param {Number} scale 容器宽度 Outer wrapper
    * @param {Number} i
  • 容器index Img wrapper's index
    * @param {Number} offset 滑动距离 move distance
    */

    /**
    * enable damping when slider meet the edge
    */
    iSlider.prototype._setUpDamping = function () {
    var oneIn2 = this.scale >> 1;
    var oneIn4 = oneIn2 >> 1;
    var oneIn16 = oneIn4 >> 2;

    this._damping = function (distance) {
    var dis = Math.abs(distance);
    var result;

    if (dis < oneIn2) { result = dis >> 1;
    } else if (dis < oneIn2 + oneIn4) { result = oneIn4 + ((dis - oneIn2) >> 2);
    } else {
    result = oneIn4 + oneIn16 + ((dis - oneIn2 - oneIn4) >> 3);
    }

    return distance > 0 ? result : -result;
    };
    };

    /**
    * render single item html by idx
    */
    iSlider.prototype._renderItem = function (el, i) {
    var item;
    var html;
    var len = this.data.length;

    // get the right item of data
    if (!this.isLooping) {
    item = this.data[i] || {empty: true};
    } else {
    if (i < 0) { item = this.data[len + i]; } else if (i > len - 1) {
    item = this.data[i - len];
    } else {
    item = this.data[i];
    }
    }

    if (item.empty) {
    el.innerHTML = '';
    el.style.background = '';
    return ;
    }
    if (this.type === 'pic') {
    // 如果不写width height,就自动匹配为dom的宽高
    if(typeof item.width==="undefined") item.width=this.width;
    if(typeof item.height==="undefined") item.height=this.height;
    if (!this.isOverspread) {
    html = item.height / item.width > this.ratio
    ? ''
    : '';
    // html=''
    } else {
    el.style.background = 'url(' + item.content + ') 50% 50% / cover no-repeat'; //ios6及以下不支持这个写法,所以~
    }
    }
    else if (this.type === 'dom') {
    html = item.content;
    }

    html && (el.innerHTML = html);
    };

    /**
    * render list html
    */
    iSlider.prototype._renderHTML = function () {
    var that=this;
    this.outer && (this.outer.innerHTML = '');
    console.log(that.dotOutside)
    // initail ul element
    var outer = this.outer || document.createElement('ul');
    outer.style.cssText = 'height:' + (this.height-that.dotOutside) + 'px;width:' + this.width + 'px;';

    // storage li elements, only store 3 elements to reduce memory usage
    this.els = [];
    for (var i = 0; i < 3; i++) {
    var li = document.createElement('li');
    li.style.cssText = 'height:' + (this.height-that.dotOutside) + 'px;width:' + this.width + 'px;';
    this.els.push(li);

    // prepare style animation
    this._animateFunc(li, this.axis, this.scale, i, 0);
    if (this.isVertical && (this._opts.animateType === 'rotate' || this._opts.animateType === 'flip')) {
    this._renderItem(li, 1 - i + this.slideIndex);
    } else {
    this._renderItem(li, i - 1 + this.slideIndex);
    }
    outer.appendChild(li);
    }

    // append ul to div#canvas
    if (!this.outer) {
    this.outer = outer;
    this.wrap.appendChild(outer);
    }
    };

    /**
    * slide logical, goto data index
    */
    iSlider.prototype.slideTo = function (dataIndex) {
    var data = this.data;
    var els = this.els;
    var idx = dataIndex;
    var n = dataIndex - this.slideIndex;
    var self=this;

    if (Math.abs(n) > 1) {
    var nextEls = n > 0 ? this.els[2] : this.els[0]
    this._renderItem(nextEls, idx);
    }

    // get right item of data
    if (data[idx]) {
    this.slideIndex = idx;
    } else {
    if (this.isLooping) {
    this.slideIndex = n > 0 ? 0 : data.length - 1;
    } else {
    this.slideIndex = this.slideIndex;
    n = 0;
    }
    }

    this.log('pic idx:' + this.slideIndex);

    // keep the right order of items
    var sEle;
    if (this.isVertical && (this._opts.animateType === 'rotate' || this._opts.animateType === 'flip')) {
    if (n > 0) {
    sEle = els.pop();
    els.unshift(sEle);
    } else if (n < 0) { sEle = els.shift(); els.push(sEle); } } else { if (n > 0) {
    sEle = els.shift();
    els.push(sEle);
    } else if (n < 0) {
    sEle = els.pop();
    els.unshift(sEle);
    }
    }

    // slidechange should render new item
    // and change new item style to fit animation
    if (n !== 0) {
    if ( Math.abs(n) > 1) {
    this._renderItem(els[0], idx - 1);
    this._renderItem(els[2], idx + 1);
    } else if (Math.abs(n) === 1) {
    this._renderItem(sEle, idx + n);
    }
    sEle.style.webkitTransition = 'none';
    sEle.style.visibility = 'hidden';

    setTimeout(function() {
    sEle.style.visibility = 'visible';
    }, 200);

    this.onslidechange && this.onslidechange(this.slideIndex);
    if(self.dotChange) self.dotChange();
    }

    // do the trick animation
    for (var i = 0; i < 3; i++) {
    if (els[i] !== sEle) {
    els[i].style.webkitTransition = 'all '+this.useTime+'ms ease';
    }
    this._animateFunc(els[i], this.axis, this.scale, i, 0);
    }

    // stop playing when meet the end of data
    if (this.isAutoplay && !this.isLooping && this.slideIndex === data.length - 1) {
    this.pause();
    }
    };

    /**
    * bind all event handler
    */
    iSlider.prototype._bindHandler = function() {
    var self = this;
    // judge mousemove start or end
    var isMoving = false;
    var outer = self.outer;
    // desktop event support
    var hasTouch = !!(('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch);
    var startEvt = hasTouch ? 'touchstart' : 'mousedown';
    var moveEvt = hasTouch ? 'touchmove' : 'mousemove';
    var endEvt = hasTouch ? 'touchend' : 'mouseup';

    var startHandler = function(evt) {
    isMoving = true;

    self.pause();
    self.onslidestart && self.onslidestart();
    self.log('Event: beforeslide');
    self.startTime = new Date().getTime();
    self.startX = hasTouch ? evt.targetTouches[0].pageX : evt.pageX;
    self.startY = hasTouch ? evt.targetTouches[0].pageY : evt.pageY;
    };

    var moveHandler = function (evt) {
    if (isMoving) {
    self.nowX=hasTouch ? evt.targetTouches[0].pageX : evt.pageX;
    self.nowY=hasTouch ? evt.targetTouches[0].pageY : evt.pageY;
    self.deltaX = self.nowX - self.startX;
    self.deltaY = self.nowY - self.startY;
    // x轴方向移动
    if(self.isVertical){
    if(Math.abs(self.deltaY)-Math.abs(self.deltaX)>0) {
    evt.preventDefault();
    }
    } else {
    if(Math.abs(self.deltaY)-Math.abs(self.deltaX)<0) {
    evt.preventDefault();
    }
    }
    var len = self.data.length;
    var axis = self.axis;
    var currentPoint = hasTouch ? evt.targetTouches[0]['page' + axis] : evt['page' + axis];
    var offset = currentPoint - self['start' + axis];

    self.onslide && self.onslide(offset);
    self.log('Event: onslide');

    if (!self.isLooping) {
    if (offset > 0 && self.slideIndex === 0 || offset < 0 && self.slideIndex === len - 1) {
    offset = self._damping(offset);
    }
    }

    for (var i = 0; i < 3; i++) {
    var item = self.els[i];
    item.style.webkitTransition = 'all 0s';
    self._animateFunc(item, axis, self.scale, i, offset);
    }

    self.offset = offset;
    }
    };

    var endHandler = function (evt) {
    isMoving = false;

    var metric = self.offset;
    var boundary = self.scale / 2;
    var endTime = new Date().getTime();
    // a quick slide time must under 300ms
    // a quick slide should also slide at least 14 px
    boundary = endTime - self.startTime > 300 ? boundary : 14;
    if (metric >= boundary) {
    self.slideTo(self.slideIndex - 1);
    } else if (metric < -boundary) {
    self.slideTo(self.slideIndex + 1);
    } else {
    self.slideTo(self.slideIndex);
    }

    self.offset = 0;
    self.isAutoplay && self.play();
    self.onslideend && self.onslideend(self.slideIndex);
    self.log('Event: afterslide');
    if(self.dotChange) self.dotChange();
    };

    var orientationchangeHandler = function (evt) {
    setTimeout(function() {
    self.reset();
    self.log('Event: orientationchange');
    },100);
    };

    outer.addEventListener(startEvt, startHandler);
    outer.addEventListener(moveEvt, moveHandler);
    outer.addEventListener(endEvt, endHandler);
    window.addEventListener('orientationchange', orientationchangeHandler);
    };

    iSlider.prototype.reset = function() {
    this.pause();
    this._setting();
    this._renderHTML();
    this.isAutoplay && this.play();
    };

    /**
    * enable autoplay
    */
    iSlider.prototype.play = function() {
    var self = this;
    var duration = this.duration;
    clearInterval(this.autoPlayTimer);
    this.autoPlayTimer = setInterval(function () {
    self.slideTo(self.slideIndex + 1);
    }, duration);
    };

    /**
    * pause autoplay
    */
    iSlider.prototype.pause = function() {
    clearInterval(this.autoPlayTimer);
    };

    iSlider.prototype.addDot = function(color){
    if (!this.isVertical) {
    var self = this;
    var data = this.data;
    var dots = [];
    var dotWrap = document.createElement('div');
    dotWrap.className = 'islider-dot-wrap addDot'+this.wrap.getAttribute("data-num");
    var fregment = document.createDocumentFragment();
    for (var i = 0; i < data.length; i++) {
    dots[i] = document.createElement('span');
    dots[i].className = color+'-dot';
    dots[i].setAttribute('index', i);
    fregment.appendChild(dots[i]);
    if(i===0){
    dots[0].classList.add("active");
    }
    }
    dotWrap.appendChild(fregment);
    this.wrap.appendChild(dotWrap);
    // insertAfter(dotWrap,self.wrap);
    }
    // function insertAfter(newEl, targetEl) {
    // var parentEl = targetEl.parentNode;
    // if(parentEl.lastChild == targetEl) {
    // parentEl.appendChild(newEl);
    // }else {
    // parentEl.insertBefore(newEl,targetEl.nextSibling);
    // }
    // }
    this.dotChange=function(){
    for(var i=0;i<dots.length;i+=1){
    dots[i].classList.remove("active");
    }
    dots[self.slideIndex].classList.add("active");
    }
    }

    /**
    * plugin extend
    */
    iSlider.prototype.extend = function(plugin, main) {
    if (!main) {
    main = iSlider.prototype;
    }
    Object.keys(plugin).forEach(function(property) {
    Object.defineProperty(main, property, Object.getOwnPropertyDescriptor(plugin, property));
    });
    };

    HTML

    var islider1 = new iSlider({
    //节点获取
    dom: document.getElementById("iSlider-effect-wrapper"),
    //图片配置
    data: datalist,
    duration: 2500,
    //animateType切换方式
    //default:默认
    //rotate:旋转
    //flip:弹出
    animateType: 'rotate',
    //是否自动播放
    isAutoplay: true,
    //是否循环播放
    isLooping: true,
    onslideend: function (ret,err) {
    var a = islider1.readindex();
    vm.getxq(id.split("[")[a],title.split("[")[a],"");
    }
    // isVertical: true, 是否垂直滚动
    });
    islider1.addDot("green");
    islider1.reset();
    }

    这就是islider的代码了,如果有报错欢迎评论,我会尽快给你们解答