关键字:移动端,无下拉,可滚动页面
在做移动端的H5页面时,由于手机自有的特性,整个页面具有下拉刷新功能。但如果我们仅仅是做展示页面,不希望下拉刷新,但同时也想保留整个页面的正常上下滚动,该如何做呢?
实现要点
- 禁用body上的touchmove事件
- 设置恰当的元素布局
- 使用matrix实现页面正常上下滚动
- 给body元素设置高度
禁用body上的touchmove事件
document.body.addEventListener('touchmove', (e) => {
e.preventDefault();
}, { passive: false });
设置恰当的元素布局
html
<header>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
<meta name="format-detection" content="telephone=no" />
<meta name="apple-mobile-web-app-capable" content="yes" />
</header>
<body>
<div id="container">
<div id="content">
</div>
</div>
</body>
css
#container {
height: 100%; // 在移动端,高度需要从当前环境中获取,100%无效
overflow: hidden;
position: absolute;
touch-action: none;
}
#content {
position: absolute;
}
使用matrix实现页面正常上下滚动
let contentTop = 0; // 记录要滚动元素的top值,默认情况为0,因为默认显示时,内容的头部时紧挨着容器的
const getTouchObj = (event) => ((touches) => ('0' in touches ? touches[0] : null))(event.targetTouches || event.originalEvent.targetTouches);
const windowHeight = getWindowHeight() * 0.8 * 0.786; // 滚动元素的可显示部分的高度,这个值通常都比滚动部分的高度小,不然就不需要滚动显示了。
const getPos = (touchObj) => ({ x: touchObj.pageX, y: touchObj.pageY, time: new Date() });
const getOffsetY = (start, endPos) => endPos.y - start;
const getScrollEl = () => $('#content'); // 滚动元素
const getContentHeight = () => getScrollEl().height(); // 滚动元素的高度
const getRealOffset = (offset, top) => {
if (offset > 0) { // 处理下滑
if (offset + top <= 0) return offset; // 下滑的距离没有超出顶部
return -top; // 下滑的距离超出了顶部
}
if (offset < 0) { // 处理上滑
if (Math.abs(offset) + Math.abs(top) + windowHeight <= getContentHeight()) return offset; // 上滑的距离没有超出底部
return -(getContentHeight() - Math.abs(top) - windowHeight); // 上滑的距离超出了底部
}
return 0;
};
let startY = 0;
getScrollEl().on('touchstart', (e) => { // 监听记录滑动的开始Y坐标
startY = getPos(getTouchObj(e)).y;
});
getScrollEl().on('touchmove', (e1) => {
((offsetY) => {
const offset = getRealOffset(offsetY, contentTop);
// this.setState({ offset });
if (Math.abs(offset) > 1) {
contentTop += offset;
getScrollEl().css('transform', `matrix(1, 0, 0, 1, 0, ${contentTop})`);
// console.log('real offset', offset, 'new top', contentTop);
}
})(getOffsetY(startY, getPos(getTouchObj(e1))));
startY = getPos(getTouchObj(e1)).y; // 更新当前的滑动Y坐标
});
结尾
总算可以说些废话了,赶时间的飘过。
禁止body上使用touchmove事件的参考忘记是从哪里copy过来的了,但真的很管用,一放到代码中,整个页面就不能动了。但是我的页面高度超出了屏幕,因此,我还得继续想办法。
最后,我找到了matrix,然后知道了国内有个大牛叫张鑫旭。其实matrix用来实现页面的滚动有点屈才了。
对于项目实施来说,能用就行。上面的代码我是用起来了,但我知道这不是最好的方案。
编程也可以是一门艺术,希望各位大侠多多指教。先谢谢各位的建议。