背景:

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

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

一气之下自己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. Install LAMP Stack On Ubuntu 16.04

    原文:http://www.unixmen.com/how-to-install-lamp-stack-on-ubuntu-16-04/ LAMP is a combination of operat ...

  2. iOS:针对固定数据源,更好的封装cell

    一.介绍 在iOS开发中,tableView非常常用,能将其展示出来,它的数据源必不可少.当然数据源有动态下发的,有固定写死的,这里我只探讨固定写死的情况.对于死数据,我们在项目中经常遇到的场景就是我 ...

  3. Ubuntu安装使用SS客户端上网

    1.安装shadowsocks sudo apt-get install python-pip pip install shadowsocks 以上代码用root执行效果较好 查找shadowsock ...

  4. 如何在Angular优雅编写HTTP请求

    原文:https://segmentfault.com/a/1190000010570799 ----------------------------------------------------- ...

  5. 最经典的常用拍照姿势大全,顶级POSE

    伸出手遮阳光.   捂住一只眼睛.   手放在最旁.这是一个极具诱惑的姿势 站立,背对镜头,扭过来,仰角拍, 俩手按在头两边,歪头,或者直头,表情一般都困惑,迷茫,咬下嘴唇效果更佳.         ...

  6. 打通MySQL架构和业务的任督二脉

    目前,在很多OLTP场景中,MySQL数据库都有着广泛的应用,也有很多不同的使用方式.从数据库的业务需求.架构设计.运营维护.再到扩容迁移,不同的MySQL架构有不同的特点,适应一定的业务场景,或者解 ...

  7. SessionFactory 执行原生态的SQL语句

    public List<User> getPageIndex(int pageIndex,int topNum){ String hql = "select top(" ...

  8. php static 变量的例子

    class test { public static function a(){} public function b(){} } $obj = new test; 调用 代码 test::a(); ...

  9. 物联网架构成长之路(14)-SpringBoot整合thymeleaf

    使用thymeleaf作为模版进行测试 在pom.xml 增加依赖 <dependency> <groupId>org.springframework.boot</gro ...

  10. 菜鸟要做架构师(二)——java性能优化之for循环

    完成同样的功能,用不同的代码来实现,性能上可能会有比较大的差别,所以对于一些性能敏感的模块来说,对代码进行一定的优化还是很有必要的.今天就来说一下java代码优化的事情,今天主要聊一下对于for(wh ...