jQuery iScroll.js 모바일 스크롤 막대 미화 플러그인 페이지 1/5_jquery
공식 웹사이트: http://cubiq.org/iscroll-5
데모:
스크롤 새로 고침: http://cubiq.org/dropbox/iscroll4/examples/pull-to-refresh/
iScroll은 매우 강력합니다. 현재는 스크롤바를 커스터마이징하는 용도로만 사용하고 있습니다. 모바일 단말기에서 스크롤바를 커스터마이징할 때 iscrol의 사용법과 주의사항을 간략히 소개하겠습니다.
1. 사용법
iScroll은 스크롤할 요소를 초기화하며, iScroll의 사용을 제한하지 않습니다. 한 페이지에 요소 수.
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>
스크롤러 요소는 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이 있는 요소 브라우저는 렌더링되지 않으므로 스크롤되는 콘텐츠의 높이를 계산할 수 없습니다.
따라서 팝업 상자가 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에서는 요소가 스크롤러 경계 너머로 드래그되면 스크롤 막대가 축소됩니다. true로 설정하면 스크롤이 방지됩니다.
표시 영역을 벗어나는 것을 방지합니다. 기본값은 Android에서는 true, iOS에서는 false
fadeScrollbar false 페이드 효과가 없을 때 스크롤 막대를 숨기도록 지정합니다.
hideScrollbar 사용자 상호 작용이 없을 때 스크롤 막대 숨기기 기본값은 true
bounce 활성화 또는 비활성화 테두리 바운스, 기본값은 true
momentum 관성 활성화 또는 비활성화, 기본값은 true입니다. 이 매개변수는 리소스를 절약할 때 매우 유용합니다.
lockDirection false는 드래그 방향 잠금을 취소합니다. true 드래그는 한 방향 Up (위/아래 또는 왼쪽/오른쪽)
2.5, 일반 방법
refresh DOM 트리가 변경될 때 이 방법을 호출해야 합니다
예: setTimeout(function () { myScroll.refresh(); }, 0);
3. 스크롤 막대를 사용자 정의할 때 CSS 부분
이 필요합니다. style 다음과 같이 막대에 클래스 매개변수를 추가합니다.
var myscroll=new iScroll("wrapper",{ scrollbarClass: "myScrollbar" });
스크롤 막대는 컨테이너와 디스플레이라는 두 가지 요소로 구성됩니다. 컨테이너는 래퍼와 높이가 동일하며 디스플레이는 스크롤 막대 자체를 나타냅니다.
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 <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 모바일 스크롤입니다. 바 미화 플러그인 No. 1/5 Page_jquery 콘텐츠, 더 많은 관련 콘텐츠를 보려면 PHP 중국어 웹사이트(www.php.cn)를 참고하세요!