背景:

弹层里边有可滚动区域时,在移动端的坑我就不多说了。

找了很多解决滚动穿透的方案,最终都不能完美解决。

一气之下自己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 - 移动端的超出滚动功能,附带滚动条,可解决弹层中滚动穿透问题。的更多相关文章

  1. 解决: 移动端经mouseover显示出的弹层中链接点击问题

    通常我们会遇到这样的需求,导航菜单在鼠标划过的时候显示自定义弹层,在弹层中有一些链接需要点击后跳转或者其他一些事件.比如: $(".menu li").on("mouse ...

  2. css 之内容溢出滚动,隐藏滚动条(解决火狐浏览隐藏不了滚动条问题)

    解决火狐浏览隐藏不了滚动条问题 1.里层容器的width多17px,外层容器溢出隐藏,能兼容各个浏览器 .outContainer { width:350px; height:300px; overf ...

  3. 弹层蒙版(mask),ios滚动穿透,我们项目的解决方案

    问题描述 项目开发遇到一个ios独有的问题,在wkwebview中稳定复现 问题: 弹出一个蒙版,当在蒙版上面滑动的时候蒙版后面的内容滚动了 这当然是ios的bug,但是经过我们测试iphone7也会 ...

  4. C# 在RichTextBox中滚动鼠标时滚动的是父窗口的滚动条

    1. RichTextBox u2 = new RichTextBox(); 2. 先记住日RichTextBox没有显示滚动条时的总宽度和显示宽度 u2.Width - u2.ClientSize. ...

  5. 基于animate.css动画库的全屏滚动小插件,适用于vue.js(移动端、pc)项目

    功能简介 基于animate.css动画库的全屏滚动,适用于vue.js(移动端.pc)项目. 安装 npm install vue-animate-fullpage --save 使用 main.j ...

  6. 原生js移动端列表无缝间歇向上滚动

    在项目开发中尤其是在项目的活动页面的开发中,经常需要将用户的购买信息或中奖信息等以列表的形式展示在页面当中,并可以使其自动间歇向上滚动来达到在有限的区域内展示所有信息的目的.通常的做法是通过将列表父元 ...

  7. JS pc端和移动端共同实现复制到剪贴板功能实现

    JS pc端和移动端实现复制到剪贴板功能实现 在网页上复制文本到剪切板,一般是使用JS+Flash结合的方法,网上有很多相关文章介绍.随着 HTML5 技术的发展,Flash 已经在很多场合不适用了, ...

  8. vue.js移动端app实战4:上拉加载以及下拉刷新

    上拉加载以及下拉刷新都是移动端很常见的功能,在搜索或者一些分类列表页面常常会用到. 跟横向滚动一样,我们还是采用better-scroll这个库来实现.由于better已经更新了新的版本,之前是0.几 ...

  9. 基于Vue.js PC桌面端弹出框组件|vue自定义弹层组件|vue模态框

    vue.js构建的轻量级PC网页端交互式弹层组件VLayer. 前段时间有分享过一个vue移动端弹窗组件,今天给大家分享一个最近开发的vue pc端弹出层组件. VLayer 一款集Alert.Dia ...

随机推荐

  1. eclim CSearch macro 问题的解决过程备忘录

    问题: CSearch 宏时. RuntimeException: Could not find file with URI because it is a relative path, and no ...

  2. 将 LDAP 目录用于 Samba 认证

    原文地址: http://www.ibm.com/developerworks/cn/education/linux/smb-ldap/smb-ldap.html 开放源码 Samba 将 Unix ...

  3. 【docker】docker部署spring boot服务,但是docker logs查看容器输出控制台日志,没有日志打印,日志未打印,docker logs不打印容器日志

    如题: docker部署spring boot服务,但是docker logs查看容器输出控制台日志,没有日志打印,日志未打印,docker logs不打印容器日志 场景再现: docker部署并启动 ...

  4. 【C#】Visual Studio 2017 一边Debug,一边修改代码

    好久没写C#了,最近在学习著名***工具 shadowsocks-windows 的源代码,想着可以边断点调试,边加上一些注释以方便理解,stackoverflow 和 msdn 随便翻了一下,竟发现 ...

  5. opencv error: undefined reference to `png_set_expand_gray_1_2_4_to_8@PNG16_0'

    问题1:/usr/bin/ld: warning: libpng16.so.16, needed by /home/andrei/anaconda/lib/libopencv_highgui.so, ...

  6. tensorflow之数据读取探究(2)

    tensorflow之tfrecord数据读取 Tensorflow关于TFRecord格式文件的处理.模型的训练的架构为: 1.获取文件列表.创建文件队列:http://blog.csdn.net/ ...

  7. iOS开发-命令模式

    命令模式算是设计模式中比较简单的,最常见的例子是工作任务安排下来进行编程,如果工作任务不需要完成,我们可以取消我们之前完成的代码,也可以理解为回滚撤销操作.这里面涉及到命令模式中的两个对象,一个是动作 ...

  8. centos7下opencv3的安装

    前面说过opencv和python模块的安装,版本是基于opencv 2的,这篇主要说一下opencv3的安装过程以及相关依赖问题的解决,同样opencv3的安装包在官网上可以下载,最新稳定版是3.3 ...

  9. Java 下一代: 函数式编码风格——Groovy、Scala 和 Clojure 共享的函数结构及其优势

    原文地址 本文内容 命令式处理 函数式处理 函数式编程的优势 所有 Java 下一代语言都包括函数式编程结构,让您可以从一个更高的抽象层面来思考问题.然而,语言间术语的不同使得难以看到类似的结构.本期 ...

  10. C# System.Collections.Stack

    using System; using System.Collections; public class SamplesStack { public static void Main() { // C ...