jQuery iScroll.js 移动端滚动条美化插件第1/5页

官网:http://cubiq.org/iscroll-5

demo:

滚动刷新:http://cubiq.org/dropbox/iscroll4/examples/pull-to-refresh/

 'Carousel' demo

iScroll功能很强大,目前我只用来 自定义滚动条 以下简单介绍一下iscrol在移动端自定义滚动条时的使用和注意事项。

一、用法

iScroll对要滚动的元素进行初始化,且不限制一个页面中使用iScroll的元素个数。

使用iScroll时,DOM树的结构要足够简单,移除不必要的标签,避免过多的标签嵌套。

1、html部分

1.1、最优最简单的iScroll结构

<div id="wrapper">

<ul>

<li></li>

.....

</ul>

</div>

本例中,ul标签将被滚动。iScroll一定要与滚动内容外的wrapper配合才能生效。

1.2、只有wrapper里的第一个子元素才可以滚动

因为只有wrapper里的第一个子元素才科院滚动,所以要让多个元素滚动 ,写法如下:

<div id="wrapper">

<div id="scroller">

<ul>

<li></li>

...

</ul>

<ul>

<li></li>

...

</ul>

</div>

</div>

scroller这个元素可以滚动,即便它包含两个ul元素。

2、js调用部分

2.1 、使用onDomContentLoaded事件实现滚动

适用于滚动内容只包含文字、图片,并且所有的图片都有固定的尺寸

<script src="iscroll.js"></script>

<script>

var myscroll; //myscroll是全局变量,可以在任意地方调用

function loaded(){

myscroll=new iScroll("wrapper");

} window.addEventListener("DOMContentLoaded",loaded,false);

</script>

2.2、使用onLoad事件实现滚动

因为DOMContentLoaded事件是载入DOM结构后就会被调用,所以在图片等元素未载入前可能无法确定滚动区域的长宽,此时可以使用onLoad事件来实现。

<script src="iscroll.js"><script>

<script>

var myscroll;

function loaded(){

setTimeout(function(){

myscroll=new iScroll("wrapper");

},100 );

}

window.addEventListener("load",loaded,false);

</script>

这种情况下iScroll会在页面资源(包括图片)加载完毕100ms之后得到初始化,这应该是一种比较安全的调用iScroll的方式。

2.3、弹框中的滚动条加载

弹框一般用display:none和display:block切换来实现。

display:none的元素浏览器没有渲染,所以无法计算滚动内容的高度。

所以在弹框调用show()显示出来后,再实例化滚动条区域。如下:

$("#mobile_show_duobao_all_num").show();

new iScroll('tc-wrapper2', {

scrollbarClass: 'myScrollbar' ,

hScrollbar:false,

vScroll:true,

hideScrollbar: false //是否隐藏滚动条

});

提示:出现滑动屏幕时,整个页面滑动的兼容性问题,解决办法如下:

document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);

2.4、iScroll传参

iScroll里的第二个参数允许你自定义一些内容,比如是否隐藏滚动条等。常用参数如下:

hScroll false 禁止横向滚动 true横向滚动 默认为true

vScroll false 精致垂直滚动 true垂直滚动 默认为true

hScrollbar false隐藏水平方向上的滚动条

vScrollbar false 隐藏垂直方向上的滚动条

fixedScrollbar 在iOS系统上,当元素拖动超出了scroller的边界时,滚动条会收缩,设置为true可以禁止滚动条超出

scroller的可见区域。默认在Android上为true, iOS上为false

fadeScrollbar   false 指定在无渐隐效果时隐藏滚动条

hideScrollbar   在没有用户交互时隐藏滚动条 默认为true

bounce  启用或禁用边界的反弹,默认为true

momentum   启用或禁用惯性,默认为true,此参数在你想要保存资源的时候非常有用

lockDirection false取消拖动方向的锁定, true拖动只能在一个方向上(up/down 或者left/right)

2.5、通用方法

refresh 在DOM树发生变化时,应该调用此方法

eg: setTimeout(function () { myScroll.refresh(); }, 0);

3、css部分

自定义滚动条样式时需要给滚动条添加一个class参数,如下

var myscroll=new iScroll("wrapper",{

  scrollbarClass: "myScrollbar"

});

滚动条是由两个元素组合而成的:容器和显示器。容器同wrapper的高度相同,而显示器则代表的是滚动条本身。

html结果如下:

<div class="myScrollbarV">

<div></div>

</div>

css如下,可以自行修改:

@charset "utf-8";

/* CSS Document */

/**

*

* Horizontal Scrollbar

*

*/

.myScrollbarH {

position:absolute;

z-index:100;

height:8px;

bottom:1px;

left:2px;

right:7px

}

.myScrollbarH > div {

position:absolute;

z-index:100;

height:100%;

/* The following is probably what you want to customize */

background-image:-webkit-gradient(linear, 0 0, 100% 0, from(#a00), to(#f00));

background-image:-moz-linear-gradient(top, #f00, #900);

background-image:-o-linear-gradient(top, #f00, #900);

border:1px solid #900;

-webkit-background-clip:padding-box;

-moz-background-clip:padding-box;

-o-background-clip:padding-box;

background-clip:padding-box;

-webkit-box-sizing:border-box;

-moz-box-sizing:border-box;

-o-box-sizing:border-box;

box-sizing:border-box;

-webkit-border-radius:4px;

-moz-border-radius:4px;

-o-border-radius:4px;

border-radius:4px;

-webkit-box-shadow:inset 1px 1px 0 rgba(255,255,255,0.5);

-moz-box-shadow:inset 1px 1px 0 rgba(255,255,255,0.5);

-o-box-shadow:inset 1px 1px 0 rgba(255,255,255,0.5);

box-shadow:inset 1px 1px 0 rgba(255,255,255,0.5);

}

/**

*

* Vertical Scrollbar

*

*/

.myScrollbarV {

position:absolute;

z-index:100;

width:8px;bottom:7px;top:2px;right:1px

}

.myScrollbarV > div {

position:absolute;

z-index:100;

width:100%;

/* The following is probably what you want to customize */

background:-webkit-gradient(linear, 0 0, 100% 0, from(#f00), to(#900));

background-image:-moz-linear-gradient(top, #f00, #900);

background-image:-o-linear-gradient(top, #f00, #900);

border:1px solid #900;

-webkit-background-clip:padding-box;

-moz-background-clip:padding-box;

-o-background-clip:padding-box;

background-clip:padding-box;

-webkit-box-sizing:border-box;

-moz-box-sizing:border-box;

-o-box-sizing:border-box;

box-sizing:border-box;

-webkit-border-radius:4px;

-moz-border-radius:4px;

-o-border-radius:4px;

border-radius:4px;

-webkit-box-shadow:inset 1px 1px 0 rgba(255,255,255,0.5);

-moz-box-shadow:inset 1px 1px 0 rgba(255,255,255,0.5);

-o-box-shadow:inset 1px 1px 0 rgba(255,255,255,0.5);

box-shadow:inset 1px 1px 0 rgba(255,255,255,0.5);

}

二、示例

1、html+js

iScroll.js

/*!

* iScroll v4.2.5 ~ Copyright (c) 2012 Matteo Spinelli, http://cubiq.org

* Released under MIT license, http://cubiq.org/license

*/

(function(window, doc){

var m = Math,

dummyStyle = doc.createElement('div').style,

vendor = (function () {

var vendors = 't,webkitT,MozT,msT,OT'.split(','),

t,

i = 0,

l = vendors.length;

for ( ; i < l; i++ ) {

t = vendors[i] + 'ransform';

if ( t in dummyStyle ) {

return vendors[i].substr(0, vendors[i].length - 1);

}

}

return false;

})(),

cssVendor = vendor ? '-' + vendor.toLowerCase() + '-' : '',

// Style properties

transform = prefixStyle('transform'),

transitionProperty = prefixStyle('transitionProperty'),

transitionDuration = prefixStyle('transitionDuration'),

transformOrigin = prefixStyle('transformOrigin'),

transitionTimingFunction = prefixStyle('transitionTimingFunction'),

transitionDelay = prefixStyle('transitionDelay'),

// Browser capabilities

isAndroid = (/android/gi).test(navigator.appVersion),

isIDevice = (/iphone|ipad/gi).test(navigator.appVersion),

isTouchPad = (/hp-tablet/gi).test(navigator.appVersion),

has3d = prefixStyle('perspective') in dummyStyle,

hasTouch = 'ontouchstart' in window && !isTouchPad,

hasTransform = vendor !== false,

hasTransitionEnd = prefixStyle('transition') in dummyStyle,

RESIZE_EV = 'onorientationchange' in window ? 'orientationchange' : 'resize',

START_EV = hasTouch ? 'touchstart' : 'mousedown',

MOVE_EV = hasTouch ? 'touchmove' : 'mousemove',

END_EV = hasTouch ? 'touchend' : 'mouseup',

CANCEL_EV = hasTouch ? 'touchcancel' : 'mouseup',

TRNEND_EV = (function () {

if ( vendor === false ) return false;

var transitionEnd = {

'' : 'transitionend',

'webkit' : 'webkitTransitionEnd',

'Moz' : 'transitionend',

'O' : 'otransitionend',

'ms' : 'MSTransitionEnd'

};

return transitionEnd[vendor];

})(),

nextFrame = (function() {

return window.requestAnimationFrame ||

window.webkitRequestAnimationFrame ||

window.mozRequestAnimationFrame ||

window.oRequestAnimationFrame ||

window.msRequestAnimationFrame ||

function(callback) { return setTimeout(callback, 1); };

})(),

cancelFrame = (function () {

return window.cancelRequestAnimationFrame ||

window.webkitCancelAnimationFrame ||

window.webkitCancelRequestAnimationFrame ||

window.mozCancelRequestAnimationFrame ||

window.oCancelRequestAnimationFrame ||

window.msCancelRequestAnimationFrame ||

clearTimeout;

})(),

// Helpers

translateZ = has3d ? ' translateZ(0)' : '',

// Constructor

iScroll = function (el, options) {

var that = this,

i;

that.wrapper = typeof el == 'object' ? el : doc.getElementById(el);

that.wrapper.style.overflow = 'hidden';

that.scroller = that.wrapper.children[0];

// Default options

that.options = {

hScroll: true,

vScroll: true,

x: 0,

y: 0,

bounce: true,

bounceLock: false,

momentum: true,

lockDirection: true,

useTransform: true,

useTransition: false,

topOffset: 0,

checkDOMChanges: false, // Experimental

handleClick: true,

// Scrollbar

hScrollbar: true,

vScrollbar: true,

fixedScrollbar: isAndroid,

hideScrollbar: isIDevice,

fadeScrollbar: isIDevice && has3d,

scrollbarClass: '',

// Zoom

zoom: false,

zoomMin: 1,

zoomMax: 4,

doubleTapZoom: 2,

wheelAction: 'scroll',

// Snap

snap: false,

snapThreshold: 1,

// Events

onRefresh: null,

onBeforeScrollStart: function (e) { e.preventDefault(); },

onScrollStart: null,

onBeforeScrollMove: null,

onScrollMove: null,

onBeforeScrollEnd: null,

onScrollEnd: null,

onTouchEnd: null,

onDestroy: null,

onZoomStart: null,

onZoom: null,

onZoomEnd: null

};

// User defined options

for (i in options) that.options[i] = options[i];

// Set starting position

that.x = that.options.x;

that.y = that.options.y;

// Normalize options

that.options.useTransform = hasTransform && that.options.useTransform;

that.options.hScrollbar = that.options.hScroll && that.options.hScrollbar;

that.options.vScrollbar = that.options.vScroll && that.options.vScrollbar;

that.options.zoom = that.options.useTransform && that.options.zoom;

that.options.useTransition = hasTransitionEnd && that.options.useTransition;

// Helpers FIX ANDROID BUG!

// translate3d and scale doesn't work together!

// Ignoring 3d ONLY WHEN YOU SET that.options.zoom

if ( that.options.zoom && isAndroid ){

translateZ = '';

}

// Set some default styles

that.scroller.style[transitionProperty] = that.options.useTransform ? cssVendor + 'transform' : 'top left';

that.scroller.style[transitionDuration] = '0';

that.scroller.style[transformOrigin] = '0 0';

if (that.options.useTransition) that.scroller.style[transitionTimingFunction] = 'cubic-bezier(0.33,0.66,0.66,1)';

if (that.options.useTransform) that.scroller.style[transform] = 'translate(' + that.x + 'px,' + that.y + 'px)' + translateZ;

else that.scroller.style.cssText += ';position:absolute;top:' + that.y + 'px;left:' + that.x + 'px';

if (that.options.useTransition) that.options.fixedScrollbar = true;

that.refresh();

that._bind(RESIZE_EV, window);

that._bind(START_EV);

if (!hasTouch) {

if (that.options.wheelAction != 'none') {

that._bind('DOMMouseScroll');

that._bind('mousewheel');

}

}

if (that.options.checkDOMChanges) that.checkDOMTime = setInterval(function () {

that._checkDOMChanges();

}, 500);

};

// Prototype

iScroll.prototype = {

enabled: true,

x: 0,

y: 0,

steps: [],

scale: 1,

currPageX: 0, currPageY: 0,

pagesX: [], pagesY: [],

aniTime: null,

wheelZoomCount: 0,

handleEvent: function (e) {

var that = this;

switch(e.type) {

case START_EV:

if (!hasTouch && e.button !== 0) return;

that._start(e);

break;

case MOVE_EV: that._move(e); break;

case END_EV:

case CANCEL_EV: that._end(e); break;

case RESIZE_EV: that._resize(); break;

case 'DOMMouseScroll': case 'mousewheel': that._wheel(e); break;

case TRNEND_EV: that._transitionEnd(e); break;

}

},

_checkDOMChanges: function () {

if (this.moved || this.zoomed || this.animating ||

(this.scrollerW == this.scroller.offsetWidth * this.scale && this.scrollerH == this.scroller.offsetHeight * this.scale)) return;

this.refresh();

},

_scrollbar: function (dir) {

var that = this,

bar;

if (!that[dir + 'Scrollbar']) {

if (that[dir + 'ScrollbarWrapper']) {

if (hasTransform) that[dir + 'ScrollbarIndicator'].style[transform] = '';

that[dir + 'ScrollbarWrapper'].parentNode.removeChild(that[dir + 'ScrollbarWrapper']);

that[dir + 'ScrollbarWrapper'] = null;

that[dir + 'ScrollbarIndicator'] = null;

}

return;

}

if (!that[dir + 'ScrollbarWrapper']) {

// Create the scrollbar wrapper

bar = doc.createElement('div');

if (that.options.scrollbarClass) bar.className = that.options.scrollbarClass + dir.toUpperCase();

else bar.style.cssText = 'position:absolute;z-index:100;' + (dir == 'h' ? 'height:7px;bottom:1px;left:2px;right:' + (that.vScrollbar ? '7' : '2') + 'px' : 'width:7px;bottom:' + (that.hScrollbar ? '7' : '2') + 'px;top:2px;right:1px');

bar.style.cssText += ';pointer-events:none;' + cssVendor + 'transition-property:opacity;' + cssVendor + 'transition-duration:' + (that.options.fadeScrollbar ? '350ms' : '0') + ';overflow:hidden;opacity:' + (that.options.hideScrollbar ? '0' : '1');

that.wrapper.appendChild(bar);

that[dir + 'ScrollbarWrapper'] = bar;

// Create the scrollbar indicator

bar = doc.createElement('div');

if (!that.options.scrollbarClass) {

bar.style.cssText = 'position:absolute;z-index:100;background:rgba(0,0,0,0.5);border:1px solid rgba(255,255,255,0.9);' + cssVendor + 'background-clip:padding-box;' + cssVendor + 'box-sizing:border-box;' + (dir == 'h' ? 'height:100%' : 'width:100%') + ';' + cssVendor + 'border-radius:3px;border-radius:3px';

}

bar.style.cssText += ';pointer-events:none;' + cssVendor + 'transition-property:' + cssVendor + 'transform;' + cssVendor + 'transition-timing-function:cubic-bezier(0.33,0.66,0.66,1);' + cssVendor + 'transition-duration:0;' + cssVendor + 'transform: translate(0,0)' + translateZ;

if (that.options.useTransition) bar.style.cssText += ';' + cssVendor + 'transition-timing-function:cubic-bezier(0.33,0.66,0.66,1)';

that[dir + 'ScrollbarWrapper'].appendChild(bar);

that[dir + 'ScrollbarIndicator'] = bar;

}

if (dir == 'h') {

that.hScrollbarSize = that.hScrollbarWrapper.clientWidth;

that.hScrollbarIndicatorSize = m.max(m.round(that.hScrollbarSize * that.hScrollbarSize / that.scrollerW), 8);

that.hScrollbarIndicator.style.width = that.hScrollbarIndicatorSize + 'px';

that.hScrollbarMaxScroll = that.hScrollbarSize - that.hScrollbarIndicatorSize;

that.hScrollbarProp = that.hScrollbarMaxScroll / that.maxScrollX;

} else {

that.vScrollbarSize = that.vScrollbarWrapper.clientHeight;

that.vScrollbarIndicatorSize = m.max(m.round(that.vScrollbarSize * that.vScrollbarSize / that.scrollerH), 8);

that.vScrollbarIndicator.style.height = that.vScrollbarIndicatorSize + 'px';

that.vScrollbarMaxScroll = that.vScrollbarSize - that.vScrollbarIndicatorSize;

that.vScrollbarProp = that.vScrollbarMaxScroll / that.maxScrollY;

}

// Reset position

that._scrollbarPos(dir, true);

},

_resize: function () {

var that = this;

setTimeout(function () { that.refresh(); }, isAndroid ? 200 : 0);

},

_pos: function (x, y) {

if (this.zoomed) return;

x = this.hScroll ? x : 0;

y = this.vScroll ? y : 0;

if (this.options.useTransform) {

this.scroller.style[transform] = 'translate(' + x + 'px,' + y + 'px) scale(' + this.scale + ')' + translateZ;

} else {

x = m.round(x);

y = m.round(y);

this.scroller.style.left = x + 'px';

this.scroller.style.top = y + 'px';

}

this.x = x;

this.y = y;

this._scrollbarPos('h');

this._scrollbarPos('v');

},

_scrollbarPos: function (dir, hidden) {

var that = this,

pos = dir == 'h' ? that.x : that.y,

size;

if (!that[dir + 'Scrollbar']) return;

pos = that[dir + 'ScrollbarProp'] * pos;

if (pos < 0) {

if (!that.options.fixedScrollbar) {

size = that[dir + 'ScrollbarIndicatorSize'] + m.round(pos * 3);

if (size < 8) size = 8;

that[dir + 'ScrollbarIndicator'].style[dir == 'h' ? 'width' : 'height'] = size + 'px';

}

pos = 0;

} else if (pos > that[dir + 'ScrollbarMaxScroll']) {

if (!that.options.fixedScrollbar) {

size = that[dir + 'ScrollbarIndicatorSize'] - m.round((pos - that[dir + 'ScrollbarMaxScroll']) * 3);

if (size < 8) size = 8;

that[dir + 'ScrollbarIndicator'].style[dir == 'h' ? 'width' : 'height'] = size + 'px';

pos = that[dir + 'ScrollbarMaxScroll'] + (that[dir + 'ScrollbarIndicatorSize'] - size);

} else {

pos = that[dir + 'ScrollbarMaxScroll'];

}

}

that[dir + 'ScrollbarWrapper'].style[transitionDelay] = '0';

that[dir + 'ScrollbarWrapper'].style.opacity = hidden && that.options.hideScrollbar ? '0' : '1';

that[dir + 'ScrollbarIndicator'].style[transform] = 'translate(' + (dir == 'h' ? pos + 'px,0)' : '0,' + pos + 'px)') + translateZ;

},

_start: function (e) {

var that = this,

point = hasTouch ? e.touches[0] : e,

matrix, x, y,

c1, c2;

if (!that.enabled) return;

if (that.options.onBeforeScrollStart) that.options.onBeforeScrollStart.call(that, e);

if (that.options.useTransition || that.options.zoom) that._transitionTime(0);

that.moved = false;

that.animating = false;

that.zoomed = false;

that.distX = 0;

that.distY = 0;

that.absDistX = 0;

that.absDistY = 0;

that.dirX = 0;

that.dirY = 0;

// Gesture start

if (that.options.zoom && hasTouch && e.touches.length > 1) {

c1 = m.abs(e.touches[0].pageX-e.touches[1].pageX);

c2 = m.abs(e.touches[0].pageY-e.touches[1].pageY);

that.touchesDistStart = m.sqrt(c1 * c1 + c2 * c2);

that.originX = m.abs(e.touches[0].pageX + e.touches[1].pageX - that.wrapperOffsetLeft * 2) / 2 - that.x;

that.originY = m.abs(e.touches[0].pageY + e.touches[1].pageY - that.wrapperOffsetTop * 2) / 2 - that.y;

if (that.options.onZoomStart) that.options.onZoomStart.call(that, e);

}

if (that.options.momentum) {

if (that.options.useTransform) {

// Very lame general purpose alternative to CSSMatrix

matrix = getComputedStyle(that.scroller, null)[transform].replace(/[^0-9\-.,]/g, '').split(',');

x = +(matrix[12] || matrix[4]);

y = +(matrix[13] || matrix[5]);

} else {

x = +getComputedStyle(that.scroller, null).left.replace(/[^0-9-]/g, '');

y = +getComputedStyle(that.scroller, null).top.replace(/[^0-9-]/g, '');

}

if (x != that.x || y != that.y) {

if (that.options.useTransition) that._unbind(TRNEND_EV);

else cancelFrame(that.aniTime);

that.steps = [];

that._pos(x, y);

if (that.options.onScrollEnd) that.options.onScrollEnd.call(that);

}

}

that.absStartX = that.x; // Needed by snap threshold

that.absStartY = that.y;

that.startX = that.x;

that.startY = that.y;

that.pointX = point.pageX;

that.pointY = point.pageY;

that.startTime = e.timeStamp || Date.now();

if (that.options.onScrollStart) that.options.onScrollStart.call(that, e);

that._bind(MOVE_EV, window);

that._bind(END_EV, window);

that._bind(CANCEL_EV, window);

},

_move: function (e) {

var that = this,

point = hasTouch ? e.touches[0] : e,

deltaX = point.pageX - that.pointX,

deltaY = point.pageY - that.pointY,

newX = that.x + deltaX,

newY = that.y + deltaY,

c1, c2, scale,

timestamp = e.timeStamp || Date.now();

if (that.options.onBeforeScrollMove) that.options.onBeforeScrollMove.call(that, e);

// Zoom

if (that.options.zoom && hasTouch && e.touches.length > 1) {

c1 = m.abs(e.touches[0].pageX - e.touches[1].pageX);

c2 = m.abs(e.touches[0].pageY - e.touches[1].pageY);

that.touchesDist = m.sqrt(c1*c1+c2*c2);

that.zoomed = true;

scale = 1 / that.touchesDistStart * that.touchesDist * this.scale;

if (scale < that.options.zoomMin) scale = 0.5 * that.options.zoomMin * Math.pow(2.0, scale / that.options.zoomMin);

else if (scale > that.options.zoomMax) scale = 2.0 * that.options.zoomMax * Math.pow(0.5, that.options.zoomMax / scale);

that.lastScale = scale / this.scale;

newX = this.originX - this.originX * that.lastScale + this.x,

newY = this.originY - this.originY * that.lastScale + this.y;

this.scroller.style[transform] = 'translate(' + newX + 'px,' + newY + 'px) scale(' + scale + ')' + translateZ;

if (that.options.onZoom) that.options.onZoom.call(that, e);

return;

}

that.pointX = point.pageX;

that.pointY = point.pageY;

// Slow down if outside of the boundaries

if (newX > 0 || newX < that.maxScrollX) {

newX = that.options.bounce ? that.x + (deltaX / 2) : newX >= 0 || that.maxScrollX >= 0 ? 0 : that.maxScrollX;

}

if (newY > that.minScrollY || newY < that.maxScrollY) {

newY = that.options.bounce ? that.y + (deltaY / 2) : newY >= that.minScrollY || that.maxScrollY >= 0 ? that.minScrollY : that.maxScrollY;

}

that.distX += deltaX;

that.distY += deltaY;

that.absDistX = m.abs(that.distX);

that.absDistY = m.abs(that.distY);

if (that.absDistX < 6 && that.absDistY < 6) {

return;

}

// Lock direction

if (that.options.lockDirection) {

if (that.absDistX > that.absDistY + 5) {

newY = that.y;

deltaY = 0;

} else if (that.absDistY > that.absDistX + 5) {

newX = that.x;

deltaX = 0;

}

}

that.moved = true;

that._pos(newX, newY);

that.dirX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;

that.dirY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;

if (timestamp - that.startTime > 300) {

that.startTime = timestamp;

that.startX = that.x;

that.startY = that.y;

}

if (that.options.onScrollMove) that.options.onScrollMove.call(that, e);

},

_end: function (e) {

if (hasTouch && e.touches.length !== 0) return;

var that = this,

point = hasTouch ? e.changedTouches[0] : e,

target, ev,

momentumX = { dist:0, time:0 },

momentumY = { dist:0, time:0 },

duration = (e.timeStamp || Date.now()) - that.startTime,

newPosX = that.x,

newPosY = that.y,

distX, distY,

newDuration,

snap,

scale;

that._unbind(MOVE_EV, window);

that._unbind(END_EV, window);

that._unbind(CANCEL_EV, window);

if (that.options.onBeforeScrollEnd) that.options.onBeforeScrollEnd.call(that, e);

if (that.zoomed) {

scale = that.scale * that.lastScale;

scale = Math.max(that.options.zoomMin, scale);

scale = Math.min(that.options.zoomMax, scale);

that.lastScale = scale / that.scale;

that.scale = scale;

that.x = that.originX - that.originX * that.lastScale + that.x;

that.y = that.originY - that.originY * that.lastScale + that.y;

that.scroller.style[transitionDuration] = '200ms';

that.scroller.style[transform] = 'translate(' + that.x + 'px,' + that.y + 'px) scale(' + that.scale + ')' + translateZ;

that.zoomed = false;

that.refresh();

if (that.options.onZoomEnd) that.options.onZoomEnd.call(that, e);

return;

}

if (!that.moved) {

if (hasTouch) {

if (that.doubleTapTimer && that.options.zoom) {

// Double tapped

clearTimeout(that.doubleTapTimer);

that.doubleTapTimer = null;

if (that.options.onZoomStart) that.options.onZoomStart.call(that, e);

that.zoom(that.pointX, that.pointY, that.scale == 1 ? that.options.doubleTapZoom : 1);

if (that.options.onZoomEnd) {

setTimeout(function() {

that.options.onZoomEnd.call(that, e);

}, 200); // 200 is default zoom duration

}

} else if (this.options.handleClick) {

that.doubleTapTimer = setTimeout(function () {

that.doubleTapTimer = null;

// Find the last touched element

target = point.target;

while (target.nodeType != 1) target = target.parentNode;

if (target.tagName != 'SELECT' && target.tagName != 'INPUT' && target.tagName != 'TEXTAREA') {

ev = doc.createEvent('MouseEvents');

ev.initMouseEvent('click', true, true, e.view, 1,

point.screenX, point.screenY, point.clientX, point.clientY,

e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,

0, null);

ev._fake = true;

target.dispatchEvent(ev);

}

}, that.options.zoom ? 250 : 0);

}

}

that._resetPos(400);

if (that.options.onTouchEnd) that.options.onTouchEnd.call(that, e);

return;

}

if (duration < 300 && that.options.momentum) {

momentumX = newPosX ? that._momentum(newPosX - that.startX, duration, -that.x, that.scrollerW - that.wrapperW + that.x, that.options.bounce ? that.wrapperW : 0) : momentumX;

momentumY = newPosY ? that._momentum(newPosY - that.startY, duration, -that.y, (that.maxScrollY < 0 ? that.scrollerH - that.wrapperH + that.y - that.minScrollY : 0), that.options.bounce ? that.wrapperH : 0) : momentumY;

newPosX = that.x + momentumX.dist;

newPosY = that.y + momentumY.dist;

if ((that.x > 0 && newPosX > 0) || (that.x < that.maxScrollX && newPosX < that.maxScrollX)) momentumX = { dist:0, time:0 };

if ((that.y > that.minScrollY && newPosY > that.minScrollY) || (that.y < that.maxScrollY && newPosY < that.maxScrollY)) momentumY = { dist:0, time:0 };

}

if (momentumX.dist || momentumY.dist) {

newDuration = m.max(m.max(momentumX.time, momentumY.time), 10);

// Do we need to snap?

if (that.options.snap) {

distX = newPosX - that.absStartX;

distY = newPosY - that.absStartY;

if (m.abs(distX) < that.options.snapThreshold && m.abs(distY) < that.options.snapThreshold) { that.scrollTo(that.absStartX, that.absStartY, 200); }

else {

snap = that._snap(newPosX, newPosY);

newPosX = snap.x;

newPosY = snap.y;

newDuration = m.max(snap.time, newDuration);

}

}

that.scrollTo(m.round(newPosX), m.round(newPosY), newDuration);

if (that.options.onTouchEnd) that.options.onTouchEnd.call(that, e);

return;

}

// Do we need to snap?

if (that.options.snap) {

distX = newPosX - that.absStartX;

distY = newPosY - that.absStartY;

if (m.abs(distX) < that.options.snapThreshold && m.abs(distY) < that.options.snapThreshold) that.scrollTo(that.absStartX, that.absStartY, 200);

else {

snap = that._snap(that.x, that.y);

if (snap.x != that.x || snap.y != that.y) that.scrollTo(snap.x, snap.y, snap.time);

}

if (that.options.onTouchEnd) that.options.onTouchEnd.call(that, e);

return;

}

that._resetPos(200);

if (that.options.onTouchEnd) that.options.onTouchEnd.call(that, e);

},

_resetPos: function (time) {

var that = this,

resetX = that.x >= 0 ? 0 : that.x < that.maxScrollX ? that.maxScrollX : that.x,

resetY = that.y >= that.minScrollY || that.maxScrollY > 0 ? that.minScrollY : that.y < that.maxScrollY ? that.maxScrollY : that.y;

if (resetX == that.x && resetY == that.y) {

if (that.moved) {

that.moved = false;

if (that.options.onScrollEnd) that.options.onScrollEnd.call(that); // Execute custom code on scroll end

}

if (that.hScrollbar && that.options.hideScrollbar) {

if (vendor == 'webkit') that.hScrollbarWrapper.style[transitionDelay] = '300ms';

that.hScrollbarWrapper.style.opacity = '0';

}

if (that.vScrollbar && that.options.hideScrollbar) {

if (vendor == 'webkit') that.vScrollbarWrapper.style[transitionDelay] = '300ms';

that.vScrollbarWrapper.style.opacity = '0';

}

return;

}

that.scrollTo(resetX, resetY, time || 0);

},

_wheel: function (e) {

var that = this,

wheelDeltaX, wheelDeltaY,

deltaX, deltaY,

deltaScale;

if ('wheelDeltaX' in e) {

wheelDeltaX = e.wheelDeltaX / 12;

wheelDeltaY = e.wheelDeltaY / 12;

} else if('wheelDelta' in e) {

wheelDeltaX = wheelDeltaY = e.wheelDelta / 12;

} else if ('detail' in e) {

wheelDeltaX = wheelDeltaY = -e.detail * 3;

} else {

return;

}

if (that.options.wheelAction == 'zoom') {

deltaScale = that.scale * Math.pow(2, 1/3 * (wheelDeltaY ? wheelDeltaY / Math.abs(wheelDeltaY) : 0));

if (deltaScale < that.options.zoomMin) deltaScale = that.options.zoomMin;

if (deltaScale > that.options.zoomMax) deltaScale = that.options.zoomMax;

if (deltaScale != that.scale) {

if (!that.wheelZoomCount && that.options.onZoomStart) that.options.onZoomStart.call(that, e);

that.wheelZoomCount++;

that.zoom(e.pageX, e.pageY, deltaScale, 400);

setTimeout(function() {

that.wheelZoomCount--;

if (!that.wheelZoomCount && that.options.onZoomEnd) that.options.onZoomEnd.call(that, e);

}, 400);

}

return;

}

deltaX = that.x + wheelDeltaX;

deltaY = that.y + wheelDeltaY;

if (deltaX > 0) deltaX = 0;

else if (deltaX < that.maxScrollX) deltaX = that.maxScrollX;

if (deltaY > that.minScrollY) deltaY = that.minScrollY;

else if (deltaY < that.maxScrollY) deltaY = that.maxScrollY;

if (that.maxScrollY < 0) {

that.scrollTo(deltaX, deltaY, 0);

}

},

_transitionEnd: function (e) {

var that = this;

if (e.target != that.scroller) return;

that._unbind(TRNEND_EV);

that._startAni();

},

/**

*

* Utilities

*

*/

_startAni: function () {

var that = this,

startX = that.x, startY = that.y,

startTime = Date.now(),

step, easeOut,

animate;

if (that.animating) return;

if (!that.steps.length) {

that._resetPos(400);

return;

}

step = that.steps.shift();

if (step.x == startX && step.y == startY) step.time = 0;

that.animating = true;

that.moved = true;

if (that.options.useTransition) {

that._transitionTime(step.time);

that._pos(step.x, step.y);

that.animating = false;

if (step.time) that._bind(TRNEND_EV);

else that._resetPos(0);

return;

}

animate = function () {

var now = Date.now(),

newX, newY;

if (now >= startTime + step.time) {

that._pos(step.x, step.y);

that.animating = false;

if (that.options.onAnimationEnd) that.options.onAnimationEnd.call(that); // Execute custom code on animation end

that._startAni();

return;

}

now = (now - startTime) / step.time - 1;

easeOut = m.sqrt(1 - now * now);

newX = (step.x - startX) * easeOut + startX;

newY = (step.y - startY) * easeOut + startY;

that._pos(newX, newY);

if (that.animating) that.aniTime = nextFrame(animate);

};

animate();

},

_transitionTime: function (time) {

time += 'ms';

this.scroller.style[transitionDuration] = time;

if (this.hScrollbar) this.hScrollbarIndicator.style[transitionDuration] = time;

if (this.vScrollbar) this.vScrollbarIndicator.style[transitionDuration] = time;

},

_momentum: function (dist, time, maxDistUpper, maxDistLower, size) {

var deceleration = 0.0006,

speed = m.abs(dist) / time,

newDist = (speed * speed) / (2 * deceleration),

newTime = 0, outsideDist = 0;

// Proportinally reduce speed if we are outside of the boundaries

if (dist > 0 && newDist > maxDistUpper) {

outsideDist = size / (6 / (newDist / speed * deceleration));

maxDistUpper = maxDistUpper + outsideDist;

speed = speed * maxDistUpper / newDist;

newDist = maxDistUpper;

} else if (dist < 0 && newDist > maxDistLower) {

outsideDist = size / (6 / (newDist / speed * deceleration));

maxDistLower = maxDistLower + outsideDist;

speed = speed * maxDistLower / newDist;

newDist = maxDistLower;

}

newDist = newDist * (dist < 0 ? -1 : 1);

newTime = speed / deceleration;

return { dist: newDist, time: m.round(newTime) };

},

_offset: function (el) {

var left = -el.offsetLeft,

top = -el.offsetTop;

while (el = el.offsetParent) {

left -= el.offsetLeft;

top -= el.offsetTop;

}

if (el != this.wrapper) {

left *= this.scale;

top *= this.scale;

}

return { left: left, top: top };

},

_snap: function (x, y) {

var that = this,

i, l,

page, time,

sizeX, sizeY;

// Check page X

page = that.pagesX.length - 1;

for (i=0, l=that.pagesX.length; i<l; i++) {

if (x >= that.pagesX[i]) {

page = i;

break;

}

}

if (page == that.currPageX && page > 0 && that.dirX < 0) page--;

x = that.pagesX

12345下一页阅读全文

以上是 jQuery iScroll.js 移动端滚动条美化插件第1/5页 的全部内容, 来源链接: utcz.com/z/340401.html

回到顶部