Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iphone手机上,rc-dialog相关组件,内容部分没有阻止冒泡,可以触发页面滚动 #1947

Closed
daqi opened this issue Oct 17, 2017 · 13 comments
Assignees

Comments

@daqi
Copy link

daqi commented Oct 17, 2017

Version

1.6.11

Environment

ios

Reproduction link

https://mobile.ant.design/kitchen-sink/components/modal?lang=zh-CN

Steps to reproduce

点击"modal对话框(ios)"按钮,在内容部分上下滑动,会触发整个页面的滚动

What is expected?

不滚动

What is actually happening?

滚动

@ant-design-bot
Copy link

It will be better to write your issue/comment in English, so more people can understand you.
And this means that more people can help you or benefit from your issue/comment.
See: ant-design/ant-design#4897

@silentcloud
Copy link
Contributor

@daqi https://github.com/ant-design/ant-design-mobile/blob/master/components/modal/Modal.tsx#L30

这个是做了处理的,不应当会有问题,我这边也没能重现

@daqi
Copy link
Author

daqi commented Oct 18, 2017

@silentcloud 我也看了源码,这部分只是处理了mask,没有处理内容部分

@silentcloud
Copy link
Contributor

@daqi 不处理 content 是有原因的,当非 alert,prompt 这种,纯 modal 如果 content overflow:scroll 是没法滚动的

@silentcloud
Copy link
Contributor

silentcloud commented Oct 18, 2017

我这边处理一下内置的 alert,prompt,operation,对于modal 自身,开放出去 wrapProps(用户根据自己情况决定要不要全部处理)

@daqi
Copy link
Author

daqi commented Oct 18, 2017

@silentcloud 同意

lixiaoyang1992 pushed a commit to lixiaoyang1992/ant-design-mobile that referenced this issue Apr 26, 2018
lixiaoyang1992 pushed a commit to lixiaoyang1992/ant-design-mobile that referenced this issue Apr 26, 2018
@daqi
Copy link
Author

daqi commented Jun 7, 2018

最近整合了一个更加完善的fix的代码,送给有缘人~

function closest(el, selector) {
  const matchesSelector =
    el.matches || el.webkitMatchesSelector || el.mozMatchesSelector || el.msMatchesSelector
  while (el) {
    if (matchesSelector.call(el, selector)) {
      return el
    }
    el = el.parentElement
  }
  return null
}

/**
 * 修复antd-mobile Modal组件touch事件穿透
 * 需要滚动的地方请加class: 'scroller'
 * 参考代码:
 * https://mobile.ant.design/components/modal-cn/
 * http://www.zhangxinxu.com/study/201612/mobile-scroll-prevent-window-scroll.html
 */

export default function fixModal() {
  let data = {
    scroller: null,
    posY: 0,
    scrollY: 0,
    maxscroll: 0
  }

  function isIosModalVisible() {
    return (
      /iPhone|iPod|iPad/i.test(navigator.userAgent) &&
      document.body.style.overflow === 'hidden' &&
      document.querySelectorAll('.am-modal').length > 0
    )
  }

  document.body.addEventListener(
    'touchstart',
    function(e) {
      if (!isIosModalVisible()) return

      const scroller = closest(e.target, '.scroller')
      if (!scroller) return

      data.scroller = scroller
      // 垂直位置标记
      data.posY = e.touches[0].pageY
      data.scrollY = scroller.scrollTop
      // 是否可以滚动
      data.maxscroll = scroller.scrollHeight - scroller.clientHeight
    },
    { passive: false }
  )

  document.body.addEventListener(
    'touchmove',
    function(e) {
      if (!isIosModalVisible()) return

      if (!data.scroller) {
        return e.preventDefault()
      }

      const scrollTop = data.scroller.scrollTop
      const distanceY = e.touches[0].pageY - data.posY

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

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

  document.body.addEventListener(
    'touchend',
    function(e) {
      if (!isIosModalVisible()) return
      data.scroller = null
      data.maxscroll = 0
    },
    { passive: false }
  )
}

@duzliang
Copy link

This doesn't work on android 5.0 WebView, when I touch the Modal, the bottom layer was scrolled

@ycscholes
Copy link

补充点资料,希望对大家有用
使用 wrapProps 是无法组织冒泡的,现在默认注册滚动事件passive为true,导致了preventDefault 失效。
In Chrome stable / Safari / feature that treats document level Wheel/Mousewheel event listeners as Passive
参考 facebook/react#6436

@hb2664700
Copy link

补充点资料,希望对大家有用
使用 wrapProps 是无法组织冒泡的,现在默认注册滚动事件passive为true,导致了preventDefault 失效。
In Chrome stable / Safari / feature that treats document level Wheel/Mousewheel event listeners as Passive
参考 facebook/react#6436

@ycscholes 大哥,请教一下,antd mobile中modal怎么禁止背景背面的滚动,modal里面的内容可以滚动,确实使用wrapProps没有办法

@daqi
Copy link
Author

daqi commented Aug 12, 2019

目前比较简单的解决办法是:
打开的时候把body设成position: fixed,并记录scrollTop,
关闭的时候再还原回来

@yunsii
Copy link

yunsii commented Sep 10, 2019

这个不只是 iphone 吧,我安卓也这样啊?!

@MBearo
Copy link

MBearo commented Apr 23, 2020

可以试下在弹窗弹出时,给body添加

{
  touch-action: none;
  overscroll-behavior: none;
  -webkit-overflow-scrolling: auto;
  overflow: hidden;
}

不过只支持ios 13+

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants