副标题:充分利用网络平台的力量,实现以应用为中心的体验。
发布时间:2020年7月29日 - 8分钟阅读
今天我们想给大家介绍一下我们将Flutter带到网络上的最新进展,特别是我们正在做的与网络平台深度和原生集成的工作。
我们对Flutter的愿景是提供一个可移植的工具包,以便在任何你可能想在屏幕上画像素的地方构建美丽的体验。正如我们之前所提到的,我们有意以应用为中心,选择我们的框架和API,建立一个分层架构,可以在移动、桌面和嵌入式设备上扩展,而不影响性能或质量。
网络是我们工作的核心。Flutter最初诞生于Chrome团队的探索。它从网络的生产力和迭代开发模式中汲取灵感,我们的许多工程师都有多年构建浏览器引擎和网络标准的经验。我们将目标锁定在web浏览器上,因为它是互联网的跳动心脏:计算史上最普遍、最灵活、最广泛的应用模式。
多年来,Web平台和HTML DOM本质上是一回事。但最近,Web平台已经扩展了越来越丰富的API和功能,暴露了底层操作系统和硬件。从硬件加速的图形到shell集成和PWA,从server workers到新的布局和绘画API,对于复杂的应用程序甚至是在这个基础上层层叠加的框架来说,web是一个越来越有力的目标。
Flutter的web支持并不是简单的DOM的移植器:它充分利用了这套新兴的API,提供了一种既忠于web又不失Flutter的表达方式的体验。
在这篇文章中,我们对这个故事进行了更深入的了解,分享了Flutter如何利用网络来实现丰富的交互体验,而无需重写现有的Flutter代码。我们还讨论了像可访问性和后端编译选择这样的领域,这些领域对于一个普通的实验者来说可能并不明显。
详述Canvas绘制
将Flutter小部件画成网页上的像素,到底是什么意思呢?
我们先来回顾一下Flutter的网页架构。Flutter是一个多层系统:
- 一个框架,它为常见的习惯用语提供了抽象,比如小部件,动画和手势。
- 一个引擎,使用其公开的系统API渲染到目标设备。
框架代码是用Dart编写的。我们将其与您自己的代码相结合,并在编译时应用剪枝算法,因此只有您的应用程序使用的代码才会下载到浏览器。Flutter采用的是反应式模型,根据状态变化来渲染用户界面。在每一帧内,Flutter构建部件,执行布局,最后使用底层的浏览器API对用户界面进行描绘。
Flutter的web架构是多层系统,在浏览器引擎之上有一个Framework
默认情况下,web模式使用标准的HTML DOM和Canvas技术。在这种模式下,引擎将每个生成的Flutter场景翻译成HTML、CSS或Canvas,并以HTML元素树的形式将框架渲染到页面上。
我们把这种方法称为DomCanvas后端。它为我们提供了最强的跨浏览器兼容性,代码大小紧凑,非常适合那些需要快速启动的短时会话的应用。
在我们继续在DomCanvas的性能和保真度上取得良好进展的同时,我们也在同步开发基于CanvasKit的后端,它可以在浏览器中使用WebAssembly和WebGL渲染Skia的绘画命令。我们开始尝试使用CanvasKit,因为Skia是Flutter移动和桌面使用的相同的图形引擎,与HTML DOM不同,它允许直接访问低级图形堆栈,从而实现与原生Flutter的完全对等。
DomCanvas提供了更广泛的浏览器支持、更小的代码尺寸、快速的初始页面加载,而CanvasKit则允许Flutter开发者拥抱新技术,构建图形密集型的Web应用。在未来,一种方法的优势可能会变得势不可挡,但现在Flutter为您提供了选择最适合您所需用例的后端的选项。
在浏览器中达到原生体验
要想让Web应用在浏览器中感觉宾至如归,它必须支持各种浏览器习惯,包括自然的文本交互和滚动行为、后向/前向导航和可访问性,所有这些都必须在各种设备和形式因素中具有良好的性能。
文本渲染
在构建Flutter的网络支持时,我们面临的最大挑战之一是开发一个专门用于文本布局的布局系统。为了布局一段文字,Flutter创建了一个段落对象,并调用其layout()方法。由于目前web缺乏直接的文本布局API,我们使用DOM通过触发layout()对段落进行各种测量,并观察框架中其他元素的布局属性的副作用。
正如你可以想象的那样,这些测量会变得相当昂贵,所以我们最近开始尝试使用canvas API来测量文本,以改进这两种后端方法。我们发现,它将文本布局性能提高了6倍,还解决了多行文本字段和文本溢出的几个问题。您可以通过发布模式标志启用这些画布文本改进。
虽然快速、正确地渲染文本对最终用户的体验很重要,但能够在浏览器上与文本交互同样重要。今天,您可以通过使用SelectableText或EditableText部件在Flutter Web应用程序上使文本可选择。很快,您也将能够复制/粘贴选定的文本,以及拥有更好的文本编辑交互,包括文本字段焦点处理、表单编辑等。
滚动
滚动有两种方式可以让Flutter网页应用感觉更自然:滚动性能和滚动承受力。
不管是移动应用还是web应用,滚动性能可以决定一个应用是否被认为是 "janky"。对于我们的渲染系统来说,滚动定义了我们如何以及何时加载内容的特定使用模式。在过去的一个季度里,我们特别注重提高滚动的性能,通过优化静态内容滚动和添加性能基准来确保我们在未来不会退步。
由于Flutter的框架最初是为原生移动应用设计的,因此Flutter Web应用已经对移动浏览器的手势和滚动物理学有了很好的支持。桌面浏览器的滚动行为取决于我们在框架层面为Flutter桌面所做的工作。到目前为止,我们能够处理用鼠标和其他鼠标/滚轮事件的拖动滚动,但我们仍然需要添加键盘滚动支持。
导航
与原生应用不同,Web应用在浏览器中内置了一个后退按钮。如今,浏览器的后退按钮的行为就像任何Flutter应用中的Navigator.pop()一样。这意味着,当用户在浏览器中打开Flutter Web应用的链接时,框架会将初始路线分成几个部分,并推送每个部分。
今天以Flutter的导航支持为例,你可以尝试从google.com到gallery.flutter.dev/#/demo/bann…,然后点击浏览器返回按钮。
你会注意到它并没有像你所期望的那样带你回到google.com,而是回到了网站的主页:gallery.flutter.dev。Flutter分割了最初的画廊应用路径,同时推送gallery.flutter.dev和/demo/banner页面,所以当浏览器返回按钮触发Navigator.pop()时,它会回到gallery.flutter.dev,因为这就是应用内部历史的设置方式。
目前正在努力改善Flutter中的导航/路由,为所有平台提供Navigator 2.0和新的Router widget。这不仅将使导航更加声明和灵活,而且还将改善Flutter网络应用的路由历史如何工作。
无障碍访问
在设计上,Flutter通过构建一个与RenderObject树分离的SemanticsNode树来实现无障碍性。Flutter的可访问性系统目前是可选的,这意味着终端用户必须选择是否启用辅助技术。当启用时,SemanticsNode树是通过扫描渲染树并合并代表屏幕上单个逻辑交互元素的语义节点而产生的。
为了在网络上做到这一点,我们生成了与用作RenderObject树的DOM树平行的第二棵DOM树,并将标志、动作、标签和其他语义属性翻译成ARIA。
每一个Flutter Web应用都可以被访问。例如,一旦你首先启用了像VoiceOver这样的屏幕阅读器辅助技术,Flutter Gallery应用就可以被访问,它适用于iOS和macOS上的web应用。当你按照屏幕阅读器的指示明确启用应用的无障碍性时,你会看到一个语义树被生成。
每个Flutter网络应用都会向VoiceOver等无障碍工具暴露一个语义树。
Flutter的web语义功能已经达到了Flutter语义系统目前的同等水平,但我们需要增加自动化测试,以确保我们不会出现回归。有一些复杂的功能我们还需要支持,比如表格和元素之间的关系。
Rive:Flutter在网络上的一个展示案例。
丰富的交互式应用展示了Flutter的网络支持能力,一个典型的例子是Rive,他们今天推出了完全用Flutter构建的设计协作工具的重写。
Rive是一个动画设计应用,它允许设计师和开发人员创建高质量的资产,以便轻松地集成到任何平台上。为了将用户界面与无故障的动画实时结合起来,Rive需要在现代浏览器以及其他平台上进行大量的图形渲染和性能体验。
Rive 2 beta完全用Flutter重写,因此,从同一个代码库中提供了网页和桌面版本。他们的网页体验使用CanvasKit后端,在两个平台上提供与Skia一致的体验。敬请关注Rive即将发布的技术博客文章,描述他们如何使用Flutter重建他们的工具。现在,你可以报名参加他们有限的名额之一,试用他们的测试版网络应用。
一个视频展示了Rive 2的新功能和增强功能。
结束语
我们希望这能让您更深入地了解我们是如何充分利用网络平台的力量,为网络构建出Flutter支持。就在几年前,我们还不可能以可接受的质量和性能水平在网络上提供Flutter,但新的网络技术的引入和平台的不断进步,让我们能够利用底层设备的更多潜力。随着网络的不断发展,我们将与它一起发展,并改进我们对文本交互、滚动、导航和可访问性的支持,因为我们将继续努力实现稳定的版本。
查看我们的文档,了解如何开始构建 Flutter Web 应用程序。如果您已经建立了一些东西,我们很乐意看到它! 分享您正在进行的工作,无论是作为CodePen还是用URL。您可以在Twitter上的@flutterdev找到我们--我们迫不及待地想看到您创建的东西了!
通过www.DeepL.com/Translator(免费版)翻译