js - 移动端的超出滚动功能,附带滚动条,可解决弹层中滚动穿透问题。
背景:
弹层里边有可滚动区域时,在移动端的坑我就不多说了。
找了很多解决滚动穿透的方案,最终都不能完美解决。
一气之下自己js撸了一个。
效果图:

原理:
1、解决滚动穿透:通过给弹层绑定touchmove和mousewheel事件,取消默认行为实现。
2、取消默认行为后不能滚动:给需要滚动展示的区域绑定touchstart、touchmove和mousewheel事件,监听触发区域的Y值,对应修改可滚动区域的translateY值,实现滚动效果。
缺点/不足:
滑动起来略显卡顿,用户体验不好,有大佬给提示下怎么优化吗?
代码:
<div class="layer">
<div class="layer-box">
<h3>title
<span class="close">X</span>
</h3>
<div class="lose-list">
<ul class="layer-scroll">
<li class="lose-item">
<h3>有效降价车款1</h3>
<ul class="lose-date">
<li>10月7日5分</li>
<li>10月7日6分</li>
<li>10月7日7分</li>
<li>10月7日8分</li>
<li>10月7日9分</li>
<li>10月7日10分</li>
<li>10月7日11分</li>
<li>10月7日12分</li>
<li>10月7日13分</li>
<li>10月7日14分</li>
<li>10月7日15444分</li>
</ul>
</li>
<li class="lose-item">
<h3>有效降价车款2</h3>
<ul class="lose-date">
<li>10月7日5分</li>
<li>10月7日6分</li>
<li>10月7日7分</li>
<li>10月7日8分</li>
<li>10月7日9分</li>
<li>10月7日10分</li>
<li>10月7日11分</li>
<li>10月7日12分</li>
<li>10月7日13分</li>
<li>10月7日14分</li>
<li>10月7日15333分</li>
</ul>
</li>
<li class="lose-item">
<h3>有效降价车款3 </h3>
<ul class="lose-date">
<li>10月7日5分</li>
<li>10月7日6分</li>
<li>10月7日7分</li>
<li>10月7日8分</li>
<li>10月7日9分</li>
<li>10月7日10分</li>
<li>10月7日11分</li>
<li>10月7日12分</li>
<li>10月7日13分</li>
<li>10月7日14分</li>
<li>10月7日152222分</li>
</ul>
</li>
</ul>
<div class="right-bar">
<div class="bar-pro"></div>
</div>
</div>
</div>
</div>
myScroll({
openBtn: 'button',
layer: '.layer',
client: '.lose-list',
scroll: '.layer-scroll',
barBG: '.right-bar',
bar: '.bar-pro'
});
function myScroll(params) {
var utils = {
clientH: $(params.client).height(), //h1
scrollH: $(params.scroll).height(), //h2
barBgH: $(params.barBG).height() //h4
}
var lastY = 0,
transY = 0,
barTransY = 0,
barH = 0; //h3
function noScroll(dom) {
$(dom).on('mousewheel', function (e) {
e.preventDefault();
});
$(dom).on('touchmove', function (e) {
e.preventDefault();
});
}
function touchToBottom(target, bar) {
$(target).on('touchstart', function (e) {
e.preventDefault();
let y = e.originalEvent.touches[0].pageY;
lastY = y;
});
$(target).on('touchmove', function (e) {
e.preventDefault();
let y = e.originalEvent.touches[0].pageY,
moveY = y - lastY;
transY += moveY;
if (moveY > 0 && transY > 0) {
/* 鼠标向下移动,对应元素向上回看 */
transY = 0; //到顶
} else {
/* 鼠标向上移动,对应元素向下翻看 */
if (Math.abs(transY) >= e.currentTarget.clientHeight - utils.clientH) { //触底
transY = -(e.currentTarget.clientHeight - utils.clientH) + 1;
}
}
$(this).css('transform', `translate(0px, ${transY}px)`);
/* 移动时,滚轮的变化监听 */
var barMove = Math.abs(moveY) * utils.barBgH / utils.scrollH;
if (moveY > 0) {
barMove = -barMove;
}
barTransY += barMove;
if (moveY > 0) {
if (barTransY <= 0) {
barTransY = 0; //到顶
}
} else {
if (barTransY >= utils.barBgH - barH) {
barTransY = utils.barBgH - barH; //到底
}
}
$(bar).css('transform', `translate(0px, ${barTransY}px)`);
lastY = y;
});
/* 滚轮事件 */
$(target).on("mousewheel", function (e, delta) {
e.preventDefault();
let y = e.originalEvent.deltaY;
if (y > 0) {
/* 向下翻滚轮 wheelDeltaY的值与之相反*/
transY -= 100;
barTransY += 100 * utils.barBgH / utils.scrollH;
if (Math.abs(transY - 100) >= e.currentTarget.clientHeight - utils.clientH) { //触底
transY = -(e.currentTarget.clientHeight - utils.clientH) + 1;
}
if (barTransY > utils.barBgH - barH) {
barTransY = utils.barBgH - barH
}
} else {
/* 向上翻滚轮*/
transY += 100;
barTransY -= 100 * utils.barBgH / utils.scrollH;
if (Math.abs(transY) - 100 <= 0) {
transY = 0; //到顶
}
if (barTransY <= 0) {
barTransY = 0; //到顶
}
}
$(this).css('transform', `translate(0px, ${transY}px)`);
$(bar).css('transform', `translate(0px, ${barTransY}px)`);
});
}
noScroll(params.layer);
$(params.layer + ' .close').on('click', function () {
$(params.layer).fadeOut();
// $(params.scroll).css('transform', 'translate(0px, 0px)');
// $(params.bar).css('transform', 'translate(0px, 0px)');
});
$(params.openBtn).on('click', function () {
$(params.scroll).css('transform', 'translate(0px, 0px)');
$(params.bar).css('transform', 'translate(0px, 0px)');
lastY = 0;
transY = 0;
barTransY = 0;
$(params.layer).fadeIn();
utils = {
clientH: $(params.client).height(), //h1
scrollH: $(params.scroll).height(), //h2
barBgH: $(params.barBG).height() //h4
}
barH = parseInt(utils.clientH * utils.barBgH / utils.scrollH); //h3
$(params.bar).height(barH + 'px');
if (utils.clientH < utils.scrollH) {
touchToBottom(params.scroll, params.bar);
}
});
}
完整demo见github:
声明:
请尊重博客园原创精神,转载或使用图片请注明:
博主:xing.org1^
出处:http://www.cnblogs.com/padding1015/
js - 移动端的超出滚动功能,附带滚动条,可解决弹层中滚动穿透问题。的更多相关文章
- 解决: 移动端经mouseover显示出的弹层中链接点击问题
通常我们会遇到这样的需求,导航菜单在鼠标划过的时候显示自定义弹层,在弹层中有一些链接需要点击后跳转或者其他一些事件.比如: $(".menu li").on("mouse ...
- css 之内容溢出滚动,隐藏滚动条(解决火狐浏览隐藏不了滚动条问题)
解决火狐浏览隐藏不了滚动条问题 1.里层容器的width多17px,外层容器溢出隐藏,能兼容各个浏览器 .outContainer { width:350px; height:300px; overf ...
- 弹层蒙版(mask),ios滚动穿透,我们项目的解决方案
问题描述 项目开发遇到一个ios独有的问题,在wkwebview中稳定复现 问题: 弹出一个蒙版,当在蒙版上面滑动的时候蒙版后面的内容滚动了 这当然是ios的bug,但是经过我们测试iphone7也会 ...
- C# 在RichTextBox中滚动鼠标时滚动的是父窗口的滚动条
1. RichTextBox u2 = new RichTextBox(); 2. 先记住日RichTextBox没有显示滚动条时的总宽度和显示宽度 u2.Width - u2.ClientSize. ...
- 基于animate.css动画库的全屏滚动小插件,适用于vue.js(移动端、pc)项目
功能简介 基于animate.css动画库的全屏滚动,适用于vue.js(移动端.pc)项目. 安装 npm install vue-animate-fullpage --save 使用 main.j ...
- 原生js移动端列表无缝间歇向上滚动
在项目开发中尤其是在项目的活动页面的开发中,经常需要将用户的购买信息或中奖信息等以列表的形式展示在页面当中,并可以使其自动间歇向上滚动来达到在有限的区域内展示所有信息的目的.通常的做法是通过将列表父元 ...
- JS pc端和移动端共同实现复制到剪贴板功能实现
JS pc端和移动端实现复制到剪贴板功能实现 在网页上复制文本到剪切板,一般是使用JS+Flash结合的方法,网上有很多相关文章介绍.随着 HTML5 技术的发展,Flash 已经在很多场合不适用了, ...
- vue.js移动端app实战4:上拉加载以及下拉刷新
上拉加载以及下拉刷新都是移动端很常见的功能,在搜索或者一些分类列表页面常常会用到. 跟横向滚动一样,我们还是采用better-scroll这个库来实现.由于better已经更新了新的版本,之前是0.几 ...
- 基于Vue.js PC桌面端弹出框组件|vue自定义弹层组件|vue模态框
vue.js构建的轻量级PC网页端交互式弹层组件VLayer. 前段时间有分享过一个vue移动端弹窗组件,今天给大家分享一个最近开发的vue pc端弹出层组件. VLayer 一款集Alert.Dia ...
随机推荐
- Install windows server 2008 on ESXi 5.1, add to domain and config for remote desktop
Never give up ---xingyunpi Install windows server 2008 system on ESXi 5.1, add it to a domain and do ...
- wcstombs_s 宽字节转多字节
// crt_wcstombs_s.c // This example converts a wide character // string to a multibyte character str ...
- IDA反汇编学习
1 转自:http://www.cnblogs.com/vento/archive/2013/02/09/2909579.html IDA Pro是一款强大的反汇编软件,特有的IDA视图和交叉引用,可 ...
- 浅谈压缩感知(二十二):压缩感知重构算法之正则化正交匹配追踪(ROMP)
主要内容: ROMP的算法流程 ROMP的MATLAB实现 一维信号的实验与结果 测量数M与重构成功概率关系的实验与结果 一.ROMP的算法流程 正则化正交匹配追踪ROMP算法流程与OMP的最大不同之 ...
- OpenCV 学习笔记 04 深度估计与分割——GrabCut算法与分水岭算法
1 使用普通摄像头进行深度估计 1.1 深度估计原理 这里会用到几何学中的极几何(Epipolar Geometry),它属于立体视觉(stereo vision)几何学,立体视觉是计算机视觉的一个分 ...
- MVC 打印解决方案--SNF快速开发平台3.1
SNF-MVC打印报表方案: 报表模块创建的过程如下: 利用Stimulsoft Reports客户端报表工具新增一个报表文件 *.mrt 当然你也可以拿好用的*.mrt模版文件进行复制出来一个,我常 ...
- phpmyadmin登录提示mysqli_real_connect(): (HY000/2002): No such file or directory和mysql8登录失败的问题
网上的解决方法有很多,但都无法解决我的问题,最后在stackoverflow上找到解决方法,原文地址:https://stackoverflow.com/questions/41881123/mysq ...
- CentOS 7 安装SVN并整合HTTP访问
#!/bin/bash## -------------------------------------------------## 安装svn并整合http访问## ----------------- ...
- 2.4 Apache Axis2 快速学习手册之XMLBeans 构建Web Service
4. 使用XMLBeans生成服务(通过xml bean 命令将wsdl 文件生成java 代码) 要使用XMLBeans生成服务,请执行以下步骤. 通过在Axis2_HOME / samples / ...
- Atitit phpstorm配置attilax总结
Atitit phpstorm配置attilax总结 1. 前期准备 1 1.1. 配置interpreter 1 1.2. debug需要xdebug的支持,不管是script模式还是web模式 3 ...