jQuery iScroll.js モバイル スクロール バー美化プラグイン ページ 1/5_jquery
公式 Web サイト: http://cubiq.org/iscroll-5
デモ:
スクロール更新: http://cubiq.org/dropbox/iscroll4/examples/pull-to-refresh/
iScroll は非常に強力です、現在はスクロールバーのカスタマイズにのみ使用しています。モバイル端末でスクロールバーをカスタマイズする際のiscrollの使い方と注意点を簡単に紹介します。
1. 使用法
iScroll はスクロールされる要素を初期化し、iScroll の使用を制限しません。 1 ページの要素数。
iScroll を使用する場合、DOM ツリーの構造は十分に単純であり、不要なタグを削除し、過度のタグのネストを避ける必要があります。
1. HTML 部分
1.1. 最もシンプルな iScroll 構造
<div id="wrapper"> <ul> <li></li> ..... </ul> </div>
この例では、ul タグがスクロールされます。 iScroll を有効にするには、スクロール コンテンツの外側のラッパーと連携する必要があります。
1.2. ラッパー内の最初の子要素のみをスクロールできます。
ラッパー内の最初の子要素のみをスクロールできるため、複数の要素をスクロールするには
<div id="wrapper"> <div id="scroller"> <ul> <li></li> ... </ul> <ul> <li></li> ... </ul> </div> </div>
2 つの ul 要素が含まれている場合でも、scroller 要素はスクロールできます。
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 はページ リソース (画像を含む) がロードされてから 100 ミリ秒後に初期化されます。これは、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 の 2 番目のパラメータを使用すると、コンテンツを非表示にするかどうかなど、一部のコンテンツをカスタマイズできます。スクロールバーなど。一般的に使用されるパラメータは次のとおりです。
hScroll false 水平スクロールを無効にする true 水平スクロールのデフォルトは true
vScroll false 繊細な垂直スクロール true 垂直スクロールのデフォルトは true
hScrollbar false スクロール バーを非表示にする水平方向の
vScrollbar false は垂直方向のスクロール バーを非表示にします
fixedScrollbar iOS では、要素がスクローラーの境界を越えてドラッグされると、スクロール バーが縮小します。これを true に設定すると、スクロールを防ぐことができます。バーが
スクローラーの境界を超えないようにします。デフォルトは、Android では true、iOS では false です。
fadeScrollbar false フェード効果がない場合にスクロール バーを非表示にします。
hideScrollbar ユーザー操作がない場合にスクロール バーを非表示にします。 デフォルトは true です。
bounce 有効または無効にします。境界線 バウンス、デフォルトは true
momentum 慣性を有効または無効にします、デフォルトは true、このパラメータはリソースを節約したい場合に非常に便利です
lockDirection false はドラッグ方向のロックをキャンセルします、true はドラッグ方向のロックを解除します一方向上 (上/下または左/右)
2.5、一般メソッド
refresh DOM ツリーが変更されたときにこのメソッドを呼び出す必要があります
例: setTimeout(function () { myScroll.refresh(); }, 0);
3. スクロール バーをカスタマイズする場合、CSS 部分
はスクロールする必要があります。 style 次のように、クラス パラメータをバーに追加します。
var myscroll=new iScroll("wrapper",{ scrollbarClass: "myScrollbar" });
スクロール バーは、コンテナと表示の 2 つの要素で構成されます。コンテナーはラッパーと同じ高さで、ディスプレイはスクロール バー自体を表します。
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); }
2. 例
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 <div class="pagenum tc">当前1/5页 <strong>1</strong> <a href="80039_2.htm">2</a> <a href="80039_3.htm">3</a> <a href="80039_4.htm">4</a> <a href="80039_5.htm">5</a> <a href="80039_2.htm">下一页</a> <a href="80039_all.htm">阅读全文</a> </div>
上記は jQuery iScroll.js mobileスクロールバー美化プラグイン No. 1/ _jquery コンテンツの 5 ページ 詳細については、PHP 中国語 Web サイト (m.sbmmt.com) に注目してください。