iOS 通过溢出滚动禁用页面滚动:触摸

2024-03-12

假设我们希望通过“添加到主屏幕”使网络应用程序感觉像本机应用程序。第一步是禁用默认滚动。容易,对吧?

// window or document
window.addEventListener("touchmove", function(event) {
    // no more scrolling
    event.preventDefault();
}, false);

一切都很好,直到你添加overflow-scrolling混合。准确来说,在 iOS 上应该是-webkit-overflow-scrolling: touch.

/* #scrollable happens to be a ul */
#scrollable {
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

通过添加事件预防,容器中的硬件加速滚动不起作用,显然不是预期的效果。

明显的解决方案看起来像这样:

// you could do this for multiple elements, of course
var scrollable = document.querySelector("#scrollable");
scrollable.addEventListener("touchmove", function(event) {
    // no more bubbling :)
    event.stopPropagation();
}, false);

但是,此解决方案会带来一个问题,如果您尝试向左或向右滚动#scrollable,它恢复为默认的滚动侦听器。显然,您应该监视事件以查看是否touchmove事件是向左还是向右跟踪,对吧?不幸的是,不,因为在我不完全理解的情况下,当在容器中垂直滚动时,它也会恢复到默认的滚动侦听器。

怎么办?更糟糕的是,我们理想情况下能够处理click或个人身上的类似点击事件lis(读:touchstart):

var items = scrollable.querySelectorAll("#scrollable li");
for (var item = 0; item < items.length; item++) {
    items[item].addEventListener("touchstart", function() {
        // handle the touch start
    }, false);
}

为了解决这个问题,我们可以简单地使用click事件,但由于点击和响应之间的延迟,默认的目标是使 Web 应用程序“感觉”是原生的。为了解决这个问题,我们将添加一个事件监听器touchstart and touchend:

var items = scrollable.querySelectorAll("#scrollable li");
var activeItem = null, startTouch = null;
for (var item = 0; item < items.length; item++) {
    items[item].addEventListener("touchstart", function(event) {
        startTouch = event.touches[0];
        activeItem = this;
    }, false);
    items[item].addEventListener("touchend", function(event) {
        var touch = event.changedTouches[0];
        var deltaX = touch.pageX - startTouch.pageX
        var deltaY = touch.pageY - startTouch.pageY;
        // require the touchstart to be within 10 pixels of the touchend
        if (deltaX * deltaX + deltaY * deltaY <= 100)
            // handle "click" event
    }, false);
}

这一切都很好,但我们仍然没有解决默认页面滚动控制某些内容的问题touchmove事件。有任何想法吗?


尝试交换你的逻辑window and scrollable元素侦听器如下所示:

// window or document
window.addEventListener("touchmove", function(event) {
  if (!event.target.classList.contains('scrollable')) {
    // no more scrolling
    event.preventDefault();
  }
}, false);

// No special listeners needed on .scrollable elements

这样,您仅在尝试滚动不可滚动元素时防止默认。

您仍然会遇到一个问题,即在可滚动内容的顶部/底部开始拖动可能会导致整个应用程序“弹起”。要解决此问题,请参阅乔·兰伯特的 ScrollFix https://github.com/joelambert/ScrollFix.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

iOS 通过溢出滚动禁用页面滚动:触摸 的相关文章

随机推荐

  • 如何使 clang-format 尊重“类似表格”的代码格式

    我的代码具有按列对齐的数据或参数表 如下所示 人为的简单示例 实际代码具有更大的表 Name Size Starting val S s Dubs abc 123 X n m YZ ij q kl Name Size Starting va
  • 建议的解决方案:在分布式环境中生成唯一 ID

    我一直在浏览网络 试图找到一种解决方案 使我们能够在区域分布式环境中生成唯一的 ID 我查看了以下选项 除其他外 雪花 推特 这似乎是一个很棒的解决方案 但我只是不喜欢仅仅为了创建 ID 而必须管理另一个软件所带来的额外复杂性 现阶段缺乏文
  • Microsoft Word 中的 docx“文件已损坏”错误

    我写了一个程序 它打开docx包并更改一些
  • 使用 Java 与 MySQL 服务器的 SSL 连接

    我正在尝试使用 Java over SSL 连接到 MySQL 服务器 我收到以下异常 com mysql jdbc exceptions jdbc4 MySQLNonTransientConnectionException Cannot
  • Docker compose 和外部镜像多阶段构建

    I use Docker 多阶段构建 https docs docker com develop develop images multistage build 具体来说 使用外部图像作为 舞台 当使用多阶段构建时 您 不限于从您之前创建的
  • CLion C++ 无法读取/打开项目目录中的 .txt 文件

    我的项目目录中有一个我创建并填充了数据的 txt 文件 目录结构如下 Users asd ClionProjects ProjectWithTemplates main cpp cmake twoday txt 这是我的代码 include
  • 强制 UIImageView 的 CABasicAnimation 顺时针/逆时针旋转

    我正在制作一个钟摆的动画 该钟摆从 0 度摆动到最大 200 度 然后再返回 问题是 如果摆超过 180 度 它会通过最短路线返回到 0 度 即继续顺时针旋转 我希望它逆时针旋转 这是我的代码 right 是一个布尔值 当钟摆从左向右摆动时
  • 数据库查询生成器 toArray() laravel 4

    我正在尝试使用该方法将查询转换为数组toArray 但它不适用于查询生成器 有什么转换的想法吗 Example DB table user gt where name Jhon gt get gt toArray 如果您更喜欢使用查询生成器
  • 使用 R/ggplot2 损坏的条形图[重复]

    这个问题在这里已经有答案了 当存在一些极端计数时 我在缩放条形图时遇到困难 当它上升得更高时 很难看到较低的计数并在绘图上比较它们 我想打破条形图以重新调整它的比例 我知道重新调整比例是不好的绘图 但我只想在需要时这样做 我在附加链接中找到
  • 当用户跳过其中一个edittext并在下一个edittext上输入数据时如何提示错误?

    在此我有八个edittext 如果用户在edittext1处输入输入 则会跳过edittext 2并在edittext 3中输入数据 我需要向用户提示错误 并且try块内的else部分不会被执行 在哪里我错了我该如何纠正这个逻辑错误 pac
  • 从 Uri 类型 android 创建文件

    我正在尝试从图库中选择图像 然后将此图像转换为文件并通过 HttpPost 发送 但我总是FileNotFoundException 这是我的代码 选择照片 public void onActivityResult int requestC
  • 如何在 Flutter CustomPainter 中使用贝塞尔曲线绘制形状

    我正在尝试使用 flutter customPainter 库绘制下面的图片 我怎样才能画出这个形状 我的代码和结果 import package flutter material dart class CurvePainter exten
  • Xamarin SOAP Web 服务

    我在 Xamarin 中创建了一个便携式库项目 我想添加 Web 服务 但框架区域已关闭 这是什么原因呢 有没有人遇到过同样的问题 过期网址 111 111 11 11 8013 Services Kurum IdentityMngmnt
  • scala - 激发 Dataframe 的结果集

    我正在查询 mysql 表 val url jdbc mysql XXX XX XXX XX XX compute 1 amazonaws com 3306 pg partner val driver com mysql jdbc Driv
  • AWS DynamoDB 查询不过滤 BOOL 值

    我有一个使用 GUI 创建的用户表 并给出了电子邮件分区键 它是一个字符串 然后我使用 aws lambda 来做一个 putItem 它有 email string email protected cdn cgi l email prot
  • 嵌入模板上的任何指令均未使用属性绑定 ngif

    我正在 Angular Angular2 RC4 中创建一个简单的应用程序 但我发现很难在 Nodejs 中使用实时服务器运行该应用程序 我想帮助您了解如何解决 Chrome 控制台中出现的错误 Chrome 控制台出错 browser a
  • 检查一个数据帧是否是另一个数据帧的重新排序[重复]

    这个问题在这里已经有答案了 我有两个在两个不同场合生成的数据帧 但我怀疑它们是相等的 两者具有相同的行数和列数 从视觉上看它们似乎是相同的 除了行的排序方式不同 两者都没有可以重新排序的 ID 列 我能做的最好的事情就是通过process
  • 使用 RX Java 获取过滤器索引或第一个的优雅方法

    我正在练习 RX Java 想要获取与过滤器匹配的项目在数组中的位置 我看不到任何明显的方法来做到这一点 我正在考虑压缩范围和可迭代可观察之类的东西 但它很快就变得比 for 循环更加冗长和复杂 过去有mapWithIndex and zi
  • 将 Firebase DB 与本地数据库结合使用

    在我的应用程序中我有SQLite db 我想在用户的设备之间引入同步 Firebase DB看起来是一个可以接受的解决方案 但是Firebase DB首先是云数据库 因此 如果用户拒绝身份验证对话框并让他使用应用程序 但没有云同步 我无法将
  • iOS 通过溢出滚动禁用页面滚动:触摸

    假设我们希望通过 添加到主屏幕 使网络应用程序感觉像本机应用程序 第一步是禁用默认滚动 容易 对吧 window or document window addEventListener touchmove function event no