在项目入口引入一个第三方js文件: inobounce.js,github
为方便有时候打不开github,这里把 inobounce.js 和 inobounce.min.js代码直接贴出来
inobounce.js
/*! iNoBounce - v0.2.0 * https://github.com/lazd/iNoBounce/ * Copyright (c) 2013 Larry Davis <lazdnet@gmail.com>; Licensed BSD */ (function(global) { // Stores the Y position where the touch started var startY = 0; // Store enabled status var enabled = false; var supportsPassiveOption = false; try { var opts = Object.defineProperty({}, 'passive', { get: function() { supportsPassiveOption = true; } }); window.addEventListener('test', null, opts); } catch (e) {} var handleTouchmove = function(evt) { // Get the element that was scrolled upon var el = evt.target; // Allow zooming var zoom = window.innerWidth / window.document.documentElement.clientWidth; if (evt.touches.length > 1 || zoom !== 1) { return; } // Check all parent elements for scrollability while (el !== document.body && el !== document) { // Get some style properties var style = window.getComputedStyle(el); if (!style) { // If we've encountered an element we can't compute the style for, get out break; } // Ignore range input element if (el.nodeName === 'INPUT' && el.getAttribute('type') === 'range') { return; } var scrolling = style.getPropertyValue('-webkit-overflow-scrolling'); var overflowY = style.getPropertyValue('overflow-y'); var height = parseInt(style.getPropertyValue('height'), 10); // Determine if the element should scroll var isScrollable = scrolling === 'touch' && (overflowY === 'auto' || overflowY === 'scroll'); var canScroll = el.scrollHeight > el.offsetHeight; if (isScrollable && canScroll) { // Get the current Y position of the touch var curY = evt.touches ? evt.touches[0].screenY : evt.screenY; // Determine if the user is trying to scroll past the top or bottom // In this case, the window will bounce, so we have to prevent scrolling completely var isAtTop = (startY <= curY && el.scrollTop === 0); var isAtBottom = (startY >= curY && el.scrollHeight - el.scrollTop === height); // Stop a bounce bug when at the bottom or top of the scrollable element if (isAtTop || isAtBottom) { evt.preventDefault(); } // No need to continue up the DOM, we've done our job return; } // Test the next parent el = el.parentNode; } // Stop the bouncing -- no parents are scrollable evt.preventDefault(); }; var handleTouchstart = function(evt) { // Store the first Y position of the touch startY = evt.touches ? evt.touches[0].screenY : evt.screenY; }; var enable = function() { // Listen to a couple key touch events window.addEventListener('touchstart', handleTouchstart, supportsPassiveOption ? { passive : false } : false); window.addEventListener('touchmove', handleTouchmove, supportsPassiveOption ? { passive : false } : false); enabled = true; }; var disable = function() { // Stop listening window.removeEventListener('touchstart', handleTouchstart, false); window.removeEventListener('touchmove', handleTouchmove, false); enabled = false; }; var isEnabled = function() { return enabled; }; // Enable by default if the browser supports -webkit-overflow-scrolling // Test this by setting the property with JavaScript on an element that exists in the DOM // Then, see if the property is reflected in the computed style var testDiv = document.createElement('div'); document.documentElement.appendChild(testDiv); testDiv.style.WebkitOverflowScrolling = 'touch'; var scrollSupport = 'getComputedStyle' in window && window.getComputedStyle(testDiv)['-webkit-overflow-scrolling'] === 'touch'; document.documentElement.removeChild(testDiv); if (scrollSupport) { enable(); } // A module to support enabling/disabling iNoBounce var iNoBounce = { enable: enable, disable: disable, isEnabled: isEnabled }; if (typeof module !== 'undefined' && module.exports) { // Node.js Support module.exports = iNoBounce; } if (typeof global.define === 'function') { // AMD Support (function(define) { define('iNoBounce', [], function() { return iNoBounce; }); }(global.define)); } else { // Browser support global.iNoBounce = iNoBounce; } }(this));
inobounce.min.js
(function(global){var startY=0;var enabled=false;var supportsPassiveOption=false;try{var opts=Object.defineProperty({},"passive",{get:function(){supportsPassiveOption=true}});window.addEventListener("test",null,opts)}catch(e){}var handleTouchmove=function(evt){var el=evt.target;var zoom=window.innerWidth/window.document.documentElement.clientWidth;if(evt.touches.length>1||zoom!==1){return}while(el!==document.body&&el!==document){var style=window.getComputedStyle(el);if(!style){break}if(el.nodeName==="INPUT"&&el.getAttribute("type")==="range"){return}var scrolling=style.getPropertyValue("-webkit-overflow-scrolling");var overflowY=style.getPropertyValue("overflow-y");var height=parseInt(style.getPropertyValue("height"),10);var isScrollable=scrolling==="touch"&&(overflowY==="auto"||overflowY==="scroll");var canScroll=el.scrollHeight>el.offsetHeight;if(isScrollable&&canScroll){var curY=evt.touches?evt.touches[0].screenY:evt.screenY;var isAtTop=startY<=curY&&el.scrollTop===0;var isAtBottom=startY>=curY&&el.scrollHeight-el.scrollTop===height;if(isAtTop||isAtBottom){evt.preventDefault()}return}el=el.parentNode}evt.preventDefault()};var handleTouchstart=function(evt){startY=evt.touches?evt.touches[0].screenY:evt.screenY};var enable=function(){window.addEventListener("touchstart",handleTouchstart,supportsPassiveOption?{passive:false}:false);window.addEventListener("touchmove",handleTouchmove,supportsPassiveOption?{passive:false}:false);enabled=true};var disable=function(){window.removeEventListener("touchstart",handleTouchstart,false);window.removeEventListener("touchmove",handleTouchmove,false);enabled=false};var isEnabled=function(){return enabled};var testDiv=document.createElement("div");document.documentElement.appendChild(testDiv);testDiv.style.WebkitOverflowScrolling="touch";var scrollSupport="getComputedStyle"in window&&window.getComputedStyle(testDiv)["-webkit-overflow-scrolling"]==="touch";document.documentElement.removeChild(testDiv);if(scrollSupport){enable()}var iNoBounce={enable:enable,disable:disable,isEnabled:isEnabled};if(typeof module!=="undefined"&&module.exports){module.exports=iNoBounce}if(typeof global.define==="function"){(function(define){define("iNoBounce",[],function(){return iNoBounce})})(global.define)}else{global.iNoBounce=iNoBounce}})(this);
因为这个库是禁止了整个页面的滑动,所以如果页面中有其他元素需要滑动的,要给滑动元素设置一个height或max-height,还有overflow: auto; -webkit-overflow-scrolling: touch;
<style> ul { height: 115px; border: 1px solid gray; overflow: auto; -webkit-overflow-scrolling: touch; } </style> <ul> <li>List Item 1</li> <li>List Item 2</li> <li>List Item 3</li> <li>List Item 4</li> <li>List Item 5</li> <li>List Item 6</li> <li>List Item 7</li> <li>List Item 8</li> <li>List Item 9</li> <li>List Item 10</li> </ul>