demo:

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

一、用法

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

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

1、html部分

1.1、最优最简单的iScroll结构

  • .....

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

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

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

  • ...

  • ...

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

2、js调用部分

2.1 、使用onDomContentLoaded事件实现滚动

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

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

function loaded(){

myscroll=new iScroll("wrapper");

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

2.2、使用onLoad事件实现滚动

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

var myscroll;

function loaded(){

setTimeout(function(){

myscroll=new iScroll("wrapper");

},100 );

}

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

这种情况下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结果如下:

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

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

page = i;

break;

}

}

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

x = that.pagesX

最新评论

xpage 传参_jQuery iScroll.js 移动端滚动条美化插件第1/5页相关推荐

  1. iscroll.js移动端滚动插件

    <!DOCTYPE html> <html> <head><meta charset="utf-8"><title>is ...

  2. jquery 乱码 传参_jquery获取URL中参数解决中文乱码问题的两种方法

    从A页面通过url传参到B页面时,解析url参数可以用下面两种方法: 方法一:正则分析法 function getQueryString(name) { var reg = new RegExp(&q ...

  3. js 移动端 滑块验证码插件_VUE技术详解,Vue.js从入门到精通

    [Vue.js简介] Vue.js是一套构建用户界面的渐进式框架.与其他重量级框架不同的是,Vue采用自底向上增量开发的设计.Vue的核心库只关注视图层,并且非常容易学习,非常容易与其它库或已有项目整 ...

  4. JS PC端时间日历插件 功能齐全 无依赖

    时间日历插件,网上有很多版本,功能强大的,功能简单的数不尽数,那为什么我还要写一个日历插件呢? 很认真的告诉你: 我手痒了,就是闲下来随便敲敲. 开发一个功能齐全的日期选择插件 根据自己的业务需求不断 ...

  5. js bind 传参、_Node.js 在微医的应用场景及实践

    我是来自微医集团消费事业群的前端工程师高翔,这篇文章整理自我在<第一届缤纷前端技术沙龙>的主题分享<Node.js 在医疗行业的应用>,介绍了 Node.js 在微医的发展历程 ...

  6. xpage 传参_一个轻量级的Android路由框架,基于ARouter上进行改良,优化Fragment的使用,可结合XPage使用。...

    XRouter 一个轻量级的Android路由框架,基于ARouter上进行改良,优化Fragment的使用,可结合XPage使用. 关于我 特征 由于是借鉴了ARouter,拥有ARouer所有特征 ...

  7. 【小程序】跨页面传参通信 onfire.js

    在小程序开发过程中,难免会遇到一种情况,当A页面需要用户设置数据 点击进入B页面,在B页面设置成功后返回并将设置的值传递给A页面.但是wx.navigateBack()并不支持返回传参.这种情况下就可 ...

  8. js bind 传参、_Node.js 在企业中的应用实践集锦

    Node.js 在企业中的应用实践 在和一些 Nodeer 童鞋的分享交流过程中,也会听到一些声音:"Node.js 在企业中是如何应用的?有哪些大厂在实践?",于是公众号 &qu ...

  9. xpage 传参_Vuex入门、同步异步 存取值

    目的: 1.了解vuex中的各个js文件的用途 2.利用vuex存值 3.利用vuex取值 4.Vuex的异步同步加载问题 1. vuex中各个组件之间传值 1.父子组件 父组件-->子组件,通 ...

最新文章

  1. UVALive2678:Subsequence
  2. PARAMETER FILE研究
  3. mysql yum多实例_centos-7yum 安装 (mairadb) 实现 mysql 多实例
  4. 机器学习案例 特征组合——高帅富 冷启动——从微博等其他渠道搜集数据进行机器学习 用户年龄——线性分段处理...
  5. 解决服务器上安装不了centos7.4的问题
  6. 简单的并发测试工具 ab.exe ab.zip可下载 -摘自网络
  7. Redis 为什么这么快
  8. Spring Security学习(二)
  9. 【新媒体】现阶段新闻聚合的玩法
  10. Python中文问题
  11. 为什么打完篮球后手接触篮球杆会有触电感?
  12. leetcode探索二叉树(一)
  13. 采用静态编译方式防止易语言小程序被误杀
  14. 使用pytorch中预训练模型VGG19获取图像特征,得到图像embedding
  15. java/php/net/python加油站收费系统设计
  16. PE工具制作(大白菜+U盘启动模式)+系统重装
  17. 华硕飞行堡垒56789原厂Windows10系统
  18. 现有论文和作者两个实体,论文实体的属性包括题目、期刊名称、年份、期刊号;作者实体的属性包括姓名、单位、地址;一篇论文可以有多个作者,且每一位作者写过多篇论文,在每一篇论文中有作者的顺序号。请完成以下操
  19. 多边形的单边裁剪算法-JS
  20. Android PPP协议

热门文章

  1. 从“谈芯”走向“用芯” RISC-V 未来前景光明?
  2. 华为怒发公开信;锤子手机难产罗永浩陷尴尬处境;苹果错失 5G | 极客头条
  3. 微软与开源,化干戈为玉帛
  4. 为什么程序员纷纷反对微软收购GitHub?
  5. 被全球 iPhone 用户讨伐 49 天后,苹果终于为 iOS 带来手动关闭降频功能!
  6. 被苹果摆了一道的高通,亮出了一张“小米”牌
  7. matlab exe mingw,matlab笔记:安装MinGW编译器
  8. python中数据读写_【循序渐进学Python——文件中数据的读写以及操作】
  9. 进入多个页签_俄罗斯学生落地签如何办理?
  10. SpringBoot:javalist和set区别