iOS safari 如何阻止「橡皮筋效果」?
01-15
背景:
iOS 5 之後開始支持 Native Scrolling,為 Web App 帶來媲美原生應用的滾動體驗。使用十分方便只要在 CSS 中加入:HTML&
&
&
&
&
CSS
.wrapper {
overflow: auto;
-webkit-overflow-scrolling: touch;
}
但是 iOS Safari 在滑動的時候會有討厭的 「橡皮筋效果」 (Over Scroll):
設計:┌─────────────┐
│ Header │
├─────────────┤
│ │
│ Scroll Area │
│ │
├─────────────┤
│ Footer │
└─────────────┘
需求:
- Scroll Area 支持垂直區域滾動。
- 滑動 Header 和 Footer 不會引發全局的 「橡皮筋效果」。
- Scroll Area 滑動到頂部或者底部,再向上或者向下拉動不會觸發全局的 「橡皮筋效果」。
- 情況2 會觸發 Scroll Area 局部的 「橡皮筋效果」。
自問自答
有一個小類庫可以阻止這個行為:joelambert/ScrollFix
但是這是一個有限的方案:[譯] ScrollFix.js:一個 iOS5 溢出滾動的(有限)修復方案 · Issue #1 · cssmagic/blog · GitHub完美解決方案: Optimizing 「overflow:scroll」 on iOS5 [UPDATE]
HTML&
&
&
&
&
&
&
添加如下樣式:
CSS.wrapper {
overflow: auto;
-webkit-overflow-scrolling: touch;
}
.sub-wrapper {
height: 100%
overflow: auto;
}
值得注意的是 sub-wrapper 的高度必須和父容器 wrapper 的高度一致,不能包含 margin 或者 padding。這樣就可以為 wrapper 添加局部的 「橡皮筋效果」,防止觸發全局的 「橡皮筋效果」。
現在來禁用 Header 和 Footer 上效果。首先阻止全局滾動的默認行為:
function preventDefault(ev) {
ev.preventDefault()
}
document.addEventListener("touchmove", preventDefault, false)
下面判斷用戶滑動時的默認容器是否為 scroller 來操控事件冒泡,這裡把事件監聽器綁定在 document 的子元素上,這樣就可以讓我們控制是否阻止瀏覽器默認的行為:
function isScroller(el) {
// 判斷元素是否為 scroller
return el.classList.contains("scroller")
}
document.body.addEventListener("touchmove", function (ev) {
var target = ev.target
// 在 scroller 上滑動,阻止事件冒泡,啟用瀏覽器默認行為。
if (isScroller(target)) {
ev.stopPropagation()
}
}, false)
支持: iOS 5 及以上
今晚某個項目中有類似的坑。
我的業務結構如下:
&div#topfixed&
div#smooth_scroll
&div#bottomfixed
疑難雜症需求:
1. 阻止smooth_scroll的[外層]進行-webkit-overflow-scrolling2. smooth_scroll仍然保持-webkit-overflow-scrolling
坑:
在smooth_scroll的滾動區域到達頁面頂部和底部閥值的時候,再次touchmove會直接觸發原生webview的回彈效果,所以,這裡需要通過判斷手指上滑和下滑來屏蔽之。
解決方案:function restoreEvent(ev) {
var _target = ev.target,
_ss = $(_target).parents().slice(-3)[0],
_point = ev.touches[0],
_top = _ss.scrollTop;
// 什麼時候到底部
var _bottomFaVal = _ss.scrollHeight - _ss.offsetHeight;
if(_ss.id === "smooth_scroll"){
// 到達頂端
if(_top === 0) {
// 阻止向下滑動
if(_point.clientY &> Y) {
ev.preventDefault();
} else {
// 阻止冒泡
// 正常執行
ev.stopPropagation();
}
} else if(_top === _bottomFaVal) {
// 到達底部
// 阻止向上滑動
if(_point.clientY &< Y) {
ev.preventDefault();
} else {
// 阻止冒泡
// 正常執行
ev.stopPropagation();
}
} else if(_top &> 0 _top &< _bottomFaVal) {
ev.stopPropagation();
}
}
}
負責的說目前沒有完美解決方案
確定這個辦法可行么,為什麼我阻止document的touchmove事件後,頁面所有的元素都不能滾動了
用css的fixed 好像可以
https://github.com/zurb/foundation-sites/issues/7548
我選擇跳轉簡單點。
踩過坑後來答一下:
cubiq/iscroll 這個庫可以完美解決問題,兼容性問題有待考證
iOS 訪問 demo: iScroll demo: scrollbars
這種方法直接導致頁面的scroll不能滾動了,這方法不行
難道說,現在可以用DIV的滾動條了?
document.getElementByTagName("body")[0].addEventListener("touchstart", function(e) {e.preventDefault();}, false)
親測可以。。。
推薦閱讀: