mask2012 / MaskBlog

all blogs are in issues.
12 stars 5 forks source link

web移动端 出现浮层时 禁止body滚动条滚动 #9

Open mask2012 opened 6 years ago

mask2012 commented 6 years ago

此解决方案完全是张鑫旭大神的转载,原文在此 https://www.zhangxinxu.com/wordpress/2016/12/web-mobile-scroll-prevent-window-js-css/

工作中遇到弹出一个浮层,并且此浮层自带滚动条时,浮层的滚动会引起下边窗口滚动条的滚动,解决这个用简单的办法做不到。

还是张鑫旭大神想得比较周到,一剂药下去,药就除了,把这个写到公共方法里,爽得不行

smartScroll: function(container, selectorScrollable) {
        // 如果没有滚动容器选择器,或者已经绑定了滚动时间,忽略
        if (!selectorScrollable || container.data('isBindScroll')) {
            return;
        }

        // 是否是搓浏览器
        // 自己在这里添加判断和筛选
        var isSBBrowser;

        var data = {
            posY: 0,
            maxscroll: 0
        };

        // 事件处理
        container.on({
            touchstart: function(event) {
                var events = event.touches[0] || event;

                // 先求得是不是滚动元素或者滚动元素的子元素
                var elTarget = $(event.target);

                if (!elTarget.length) {
                    return;
                }

                var elScroll;

                // 获取标记的滚动元素,自身或子元素皆可
                if (elTarget.is(selectorScrollable)) {
                    elScroll = elTarget;
                } else if ((elScroll = elTarget.parents(selectorScrollable)).length == 0) {
                    elScroll = null;
                }

                if (!elScroll) {
                    return;
                }

                // 当前滚动元素标记
                data.elScroll = elScroll;

                // 垂直位置标记
                data.posY = events.pageY;
                data.scrollY = elScroll.scrollTop();
                // 是否可以滚动
                data.maxscroll = elScroll[0].scrollHeight - elScroll[0].clientHeight;
            },
            touchmove: function() {
                // 如果不足于滚动,则禁止触发整个窗体元素的滚动
                if (data.maxscroll <= 0 || isSBBrowser) {
                    // 禁止滚动
                    event.preventDefault();
                }
                // 滚动元素
                var elScroll = data.elScroll;
                // 当前的滚动高度
                var scrollTop = elScroll.scrollTop();

                // 现在移动的垂直位置,用来判断是往上移动还是往下
                var events = event.touches[0] || event;
                // 移动距离
                var distanceY = events.pageY - data.posY;

                if (isSBBrowser) {
                    elScroll.scrollTop(data.scrollY - distanceY);
                    elScroll.trigger('scroll');
                    return;
                }

                // 上下边缘检测
                if (distanceY > 0 && scrollTop == 0) {
                    // 往上滑,并且到头
                    // 禁止滚动的默认行为
                    event.preventDefault();
                    return;
                }

                // 下边缘检测
                if (distanceY < 0 && (scrollTop + 1 >= data.maxscroll)) {
                    // 往下滑,并且到头
                    // 禁止滚动的默认行为
                    event.preventDefault();
                    return;
                }
            },
            touchend: function() {
                data.maxscroll = 0;
            }
        });

        // 防止多次重复绑定
        container.data('isBindScroll', true);
    },

调用时是这样的

$.smartScroll($('#quitBoxHolder'), '.quit_box');
第一个参数是弹出层的holder元素,第二个参数是弹出层需要滚动的元素
如果弹出后只是要让后边不动,那么第二个随便写什么都行;
DongLee0504 commented 6 years ago

移动端滚动穿透解决方案

body.modal-open {
    position: fixed;
    width: 100%;
}
var ModalHelper = (function(bodyCls) {
  var scrollTop;
  return {
    afterOpen: function() {
      scrollTop = document.scrollingElement.scrollTop;
      document.body.classList.add(bodyCls);
      document.body.style.top = -scrollTop + 'px';
    },
    beforeClose: function() {
      document.body.classList.remove(bodyCls);
      // scrollTop lost after set position:fixed, restore it back.
      document.scrollingElement.scrollTop = scrollTop;
    }
  };
})('modal-open');

在modalOpen时调用ModalHelper.afterOpen(); 在modalClose时调用ModalHelper.beforeClose(); 网址链接:https://uedsky.com/2016-06/mobile-modal-scroll/ https://segmentfault.com/a/1190000005617307

mask2012 commented 6 years ago

also nice solution! 感谢你的分享!