热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

css如何让滚轮滚动时不让页面滚动_[翻译]瞧一瞧现代游览器如何工作?Part4

Insidelookatmodernwebbrowser(part4)原文地址:https:developers.google.comwebupdates201809

Inside look at modern web browser (part 4)

原文地址:https://developers.google.com/web/updates/2018/09/inside-browser-part4

用户输入进入合成器

这是了解 Chrome 如何处理您的代码以显示网站内部系列博客的最后一篇。在上一篇文章中我们了解了 Chrome 的渲染过程和合成器。本文我们将了解合成器如何实现流畅的用户交互。

从浏览器的角度看用户输入

当您听到“输入事件”时,您可能只会想到键入文本框或单击鼠标,但是从浏览器的角度来看,输入包含用户的所有手势。鼠标滚轮滚动是输入事件,触摸或鼠标悬停也是输入事件。

当用户触发手势(如屏幕上的触摸)时,浏览进程将首先接收手势。但是,浏览进程仅知道该手势发生在哪里,因为 Tab 页的内容由渲染进程处理。因此,浏览进程将事件类型(如 touchstart)及其坐标发送给渲染进程。渲染进程通过找到事件目标(EventTarget)并运行附加的事件监听器来响应输入。

b1557803f2de8fa8beaaf3f54303e024.png
图 1:输入事件从浏览器进程传递到渲染进程

合成器接收输入事件

在上一篇文章中,我们研究了合成器如何通过合并栅格化图层来平滑处理滚动。如果该页面上没有任何输入事件监听器,则合成线程可以创建一个完全独立于主线程的新合成帧。但是,如果将某些事件监听器附加到页面上怎么办?合成线程如何判断是否需要处理事件?

理解非快速滚动区域

由于 Javascript 是在主线程上运行,因此在合成页面时,合成线程会将页面上具有事件处理程序的区域标记为“非快速滚动区域”。有了这些信息,如果事件发生在该区域中,则合成线程可以确保将输入事件发送到主线程。如果输入事件来自该区域之外,则合成线程将在不等待主线程的情况下进行新帧的合成。

1b9db7116cf9c10769ed2e2a576444f8.png
图 2:非快速滚动区域发生输入事件的示意图

编写事件处理程序时的注意点

事件委托(事件代理)是一种 Web 开发中常见的事件处理模式。由于事件冒泡,您可以在最顶层的元素上附加一个事件处理程序,并根据 EventTarget 委派任务。您可能看到过或编写过如下代码:

document.body.addEventListener('touchstart', event => {if (event.target === area) {event.preventDefault();}
});

由于您只需要为所有元素编写一个事件处理程序,因此事件委托模式的功效是很吸引人的。但是,如果从浏览器的角度查看此代码,现在整个页面都被标记为不可快速滚动的区域了。这意味着,即使您的页面的某些部分不关心输入事件,合成线程也必须与主线程通信,并在每次输入事件发生时等待主线程。此时,合成线程就丧失了使页面平滑滚动的能力。

78633becb17634a2381226d9e5a2eedc.png
图 3:整个页面都是非快速滚动区时,输入事件的处理示意图

为了避免这种情况的发生,您可以在事件监听时设置 passive: true 。这会告知浏览器您仍要在主线程中监听事件,但是合成器也可以并行继续合成新的帧。

document.body.addEventListener('touchstart', event => {if (event.target === area) {event.preventDefault()}}, { passive: true });

检查事件是否可以取消

假设您在页面中有一个框,想将滚动方向限制为水平滚动。

在手势事件中使用 passive: true 可以让滚动流畅,但垂直滚动可能在你调用 preventDefault() 来阻止垂直滚动之前就开始了。您可以使用 event.cancelable 进行检查。

ec9da207073f842ce5282c68fd2c8dd1.png
图 4:页面中的部分区域固定为水平滚动

document.body.addEventListener('pointermove', event => {if (event.cancelable) {event.preventDefault(); // block the native scroll/** do what you want the application to do here*/}
}, {passive: true});

另外,您可以使用CSS规则 ​touch-action​ 来完全避免使用事件处理程序。

#area {touch-action: pan-x;
}

查找 EventTarget

当合成线程将输入事件发送到主线程时,要做的第一件事是运行命中检测以找到 EventTarget。命中检测使用在渲染阶段中生成的绘制记录来找出事件发生的点坐标对应的元素。

ad18392a76451789e9c5c49dc06709b9.png
图 5:主线程使用绘制记录查找在 x, y 的位置是什么元素

压缩分配到主线程的事件

在上一篇文章中,我们讨论了如何每秒刷新屏幕 60次,以及如何保持刷新率以实现流畅的动画。对于用户输入,常用的触摸屏设备每秒发送 60-120次触摸事件,而常用的鼠标则每秒发送 100次事件。输入事件的频率高于我们的屏幕刷新能力。

如果诸如 mousemove 这样的连续事件被以每秒钟 120次的频率传递给渲染进程的主线程,与屏幕低刷新率相比,会触发过量的命中测试和 Javascript 的回调执行。

87df995bbf8cdfaa3c189248751ee160.png
图 6:事件泛滥到帧时间轴上,导致页面卡顿

为了尽量减少对主线程过度调用,Chrome 的聚合了连续事件(如 wheel,mousewheel,mousemove,pointermove, touchmove)并延迟调度直到下一次 requestAnimationFrame 执行前。

3daf27f9a6b58098b49cb39954455132.png
图 7:与之前相同的帧时间轴,但事件被合并并延迟执行

非连续事件,如 keydown,keyup,mouseup,mousedown,touchstart,和 touchend 会被立即派发。不会进行延迟和合并。

(译者注:这也是为什么当使用扫码枪一类的输入设备时,某些键盘上正常使用的输入框,可能不再可用,特别是在使用受控方式编写 format 逻辑的情况下。)

使用 getCoalescedEvents 得到帧内事件

对于大多数 Web 应用程序,合并事件足以提供良好的用户体验。但是,如果要构建诸如画图应用程序之类的基于 touchmove 坐标路径的东西,则可能会丢失中间的坐标,而使绘制不平滑。

54566a1ad6d9150a236fd19070feebed.png
图 8:左侧是手势路径,右侧是合并结果路径,变得不平滑

window.addEventListener('pointermove', event => {const events = event.getCoalescedEvents();for (let event of events) {const x = event.pageX;const y = event.pageY;// 使用 x、y 坐标绘制路径}
});

结语

在本系列中,我们介绍了 Web 浏览器的内部工作原理。如果您从未想过为什么 DevTools 建议添加 { passive: true } 给事件处理程序,或者为什么要添加 async 标签中,那么我希望本系列文章能阐明为什么浏览器需要这些信息来提供更快,更流畅的 Web 体验。

总结

当我开始建立网站时,我几乎只关心如何编写代码以及什么可以帮助我提高效率。这些事情很重要,但是我们还应该考虑浏览器如何使用我们编写的代码。现代浏览器正持续为用户提供更好的 Web 体验而投入资源。通过组织对浏览器友好的代码,从而改善了您的用户体验。希望您加入我们的行列,以求对浏览器友好!

译者额外补充

Chrome v51 开始引入 { passive }。Chrome v55 开始 touchstart and touchmove 默认 passivetrue。Chrome v73 增加了 wheelmousewheel 事件默认 passivetrue

Pegasus:[翻译] 瞧一瞧现代游览器如何工作?Part 1​zhuanlan.zhihu.com
056e58f9a81dee5168df144946d163f0.png
Pegasus:[翻译] 瞧一瞧现代游览器如何工作?Part 2​zhuanlan.zhihu.com
a04500df813fa4794d99b59c064fb2db.png
Pegasus:[翻译] 瞧一瞧现代游览器如何工作?Part 3​zhuanlan.zhihu.com
8d058700cbf3b46f8d381520bcf4a212.png



推荐阅读
  • V8不仅是一款著名的八缸发动机,广泛应用于道奇Charger、宾利Continental GT和BossHoss摩托车中。自2008年以来,作为Chromium项目的一部分,V8 JavaScript引擎在性能优化和技术创新方面取得了显著进展。该引擎通过先进的编译技术和高效的垃圾回收机制,显著提升了JavaScript的执行效率,为现代Web应用提供了强大的支持。持续的优化和创新使得V8在处理复杂计算和大规模数据时表现更加出色,成为众多开发者和企业的首选。 ... [详细]
  • 单片微机原理P3:80C51外部拓展系统
      外部拓展其实是个相对来说很好玩的章节,可以真正开始用单片机写程序了,比较重要的是外部存储器拓展,81C55拓展,矩阵键盘,动态显示,DAC和ADC。0.IO接口电路概念与存 ... [详细]
  • php更新数据库字段的函数是,php更新数据库字段的函数是 ... [详细]
  • 在《Cocos2d-x学习笔记:基础概念解析与内存管理机制深入探讨》中,详细介绍了Cocos2d-x的基础概念,并深入分析了其内存管理机制。特别是针对Boost库引入的智能指针管理方法进行了详细的讲解,例如在处理鱼的运动过程中,可以通过编写自定义函数来动态计算角度变化,利用CallFunc回调机制实现高效的游戏逻辑控制。此外,文章还探讨了如何通过智能指针优化资源管理和避免内存泄漏,为开发者提供了实用的编程技巧和最佳实践。 ... [详细]
  • 浏览器作为我们日常不可或缺的软件工具,其背后的运作机制却鲜为人知。本文将深入探讨浏览器内核及其版本的演变历程,帮助读者更好地理解这一关键技术组件,揭示其内部运作的奥秘。 ... [详细]
  • 如何将TS文件转换为M3U8直播流:HLS与M3U8格式详解
    在视频传输领域,MP4虽然常见,但在直播场景中直接使用MP4格式存在诸多问题。例如,MP4文件的头部信息(如ftyp、moov)较大,导致初始加载时间较长,影响用户体验。相比之下,HLS(HTTP Live Streaming)协议及其M3U8格式更具优势。HLS通过将视频切分成多个小片段,并生成一个M3U8播放列表文件,实现低延迟和高稳定性。本文详细介绍了如何将TS文件转换为M3U8直播流,包括技术原理和具体操作步骤,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 卓盟科技:动态资源加载技术的兼容性优化与升级 | Android 开发者案例分享
    随着游戏内容日益复杂,资源加载过程已不仅仅是简单的进度显示,而是连接玩家与开发者的桥梁。玩家对快速加载的需求越来越高,这意味着开发者需要不断优化和提升动态资源加载技术的兼容性和性能。卓盟科技通过一系列的技术创新,不仅提高了加载速度,还确保了不同设备和系统的兼容性,为用户提供更加流畅的游戏体验。 ... [详细]
  • Spring Boot 中配置全局文件上传路径并实现文件上传功能
    本文介绍如何在 Spring Boot 项目中配置全局文件上传路径,并通过读取配置项实现文件上传功能。通过这种方式,可以更好地管理和维护文件路径。 ... [详细]
  • 如何在Java中使用DButils类
    这期内容当中小编将会给大家带来有关如何在Java中使用DButils类,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。D ... [详细]
  • 开机自启动的几种方式
    0x01快速自启动目录快速启动目录自启动方式源于Windows中的一个目录,这个目录一般叫启动或者Startup。位于该目录下的PE文件会在开机后进行自启动 ... [详细]
  • 本文将详细介绍如何在Webpack项目中安装和使用ECharts,包括全量引入和按需引入的方法,并提供一个柱状图的示例。 ... [详细]
  • 本文介绍了并查集(Union-Find算法)的基本概念及其应用。通过一个具体的例子,解释了如何使用该算法来处理涉及多个集合的问题。题目要求输入两个整数 n 和 m,分别表示总人数和操作次数。算法通过高效的合并与查找操作,能够快速确定各个元素所属的集合,适用于大规模数据的动态管理。 ... [详细]
  • 您的数据库配置是否安全?DBSAT工具助您一臂之力!
    本文探讨了Oracle提供的免费工具DBSAT,该工具能够有效协助用户检测和优化数据库配置的安全性。通过全面的分析和报告,DBSAT帮助用户识别潜在的安全漏洞,并提供针对性的改进建议,确保数据库系统的稳定性和安全性。 ... [详细]
  • 提升视觉效果:Unity3D中的HDR与Bloom技术(高动态范围成像与光线散射)
    提升视觉效果:Unity3D中的HDR与Bloom技术(高动态范围成像与光线散射) ... [详细]
  • C++ 开发实战:实用技巧与经验分享
    C++ 开发实战:实用技巧与经验分享 ... [详细]
author-avatar
三十二号t娶我吧
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有