原文地址:blogs.windows.com/msedgedev/2…
原文作者:blogs.windows.com/msedgedev/a…
发布时间:2020年9月4日
浏览器是任何设备上使用最多的应用程序之一,今天它在一个全新的硬件类别上运行:双屏和可折叠设备。
随着各种新的双屏和可折叠设备进入市场,包括上周推出的新的Surface Duo,现在是开始考虑你的网站如何拥抱这些形式因素的最好时机。
今天,我们很高兴地宣布有两个新的实验性功能可以使用,它们将帮助网站开发人员在跨越多个显示区域的浏览器窗口中有效地布置内容,并创建自然适合这种新类别设备的响应式网站。
- CSS跨屏媒体功能和一组环境变量来描述折叠的几何形状。
- JavaScript窗口段枚举API,这是CSS基元的配套API,在使用Canvas2d和WebGL等非DOM目标时非常有用。 接下来阅读这个。
可折叠设备类
广义上讲,可折叠设备有两种变体:双屏设备和利用柔性显示技术的单屏设备。两者都有很多共同点:它们都是便携式、多姿态的设备,允许用户旋转、翻转和折叠。
在这种外形上,应用程序可以驻留在一侧,也可以横跨两个显示区域。响应这种横跨状态的网站与逻辑上分割呈现的内容的语义和意图相结合。
这种设备类别所带来的广阔的屏幕空间和独特的姿态使网络开发者能够在一个可以放在口袋或钱包里的设备中释放出前所未有的网络体验。
从传统的连续屏幕过渡到双屏幕和折叠式设备
尽管现有的网站将继续开箱即用,但让网站意识到设备的可折叠性,可以大大增强用户体验。
为了更好地说明这个机会,并展示新创建的浏览器功能是如何工作的,我们将带你加强一个电子邮件客户端布局的例子。
并排显示收件箱的列表视图和电子邮件的内容是一种常见的模式,对于较宽的浏览区域来说自然是很好的。当浏览器窗口横跨双屏设备上的两个显示区域时,整体视口宽度很可能与传统的横向平板设备相当。
在未经修改的情况下,电子邮件客户端将继续像以前一样工作。然而,如果我们能将收件箱和邮件栏与折页对齐,使其保持在一个单一显示区域的边界内,那么体验就会得到极大的改善。这样一来,任何内容区域都不会被设备铰链切割或遮挡,也不会在柔性显示屏的折叠处呈现。
为了实现所需的布局,我们正在引入一个新的跨越屏幕的媒体功能和一组预定义的环境变量,允许网页开发人员将可折叠设备视为另一个响应式网页设计目标。开发人员现在可以创建适应每个设备类别的布局,而不需要对特定的硬件参数采取硬性的依赖。这种灵活性提高了可扩展性,因为它不需要为每个新设备类型重复工作。
检测显示区域
CSS跨屏媒体功能将帮助Web开发者测试根视口是否被跨越多个相邻的显示区域,并提供这些相邻显示区域的配置细节(如堆叠或并排)。
语法
跨屏媒体特征被指定为一个值,描述设备的折叠(或铰链)数量,以及它们的姿势。如果该设备不是可折叠设备,则该值为无。如果它是一个可折叠的,它可以有这两个值中的一个。
- Single-fold-vertical: 匹配具有单个折叠(两个显示区域)且折叠姿势为垂直的设备。
- Single-fold-horizontal: 匹配具有单个折叠(两个显示区域)且折叠姿态为水平的设备。
计算显示区域的几何形状
假设在跨屏状态下,折叠总是要把视口精确地分成两半,这是不安全的。此外,一些窗口管理员可能会选择屏蔽折叠后的网页内容。为了帮助网页开发者计算每个显示区域的大小,并确保他们知道他们的内容(如果有的话)需要填充多少以避免屏蔽,我们正在添加四个预定义的CSS环境变量。
- env(fold-top)
- env(fold-left)
- env(fold-width)
- env(fold-height)
这些变量的值是以CSS像素表示的,并且是相对于布局视口而言的(即在客户端坐标中,如CSSOM视图所定义)。当在不处于跨度状态之一的内容中评估时,这些值将被视为不存在,浏览器将使用传递给env()函数的回退值。
为双屏和可折叠体验增强我们的电子邮件示例应用程序
一个并列的例子显示了一个内容被铰链间隙遮挡的邮件应用,以及一个考虑到铰链间隙的布局
让我们把CSS的跨屏媒体功能和折叠几何环境变量付诸实践,增强我们邮件客户端的读者视图。
@media screen and (min-width: 799px) {
/* rules specific to screens that are wider than tablet */
}
@media screen and (min-width: 799px) and (screen-spanning: single-fold-vertical) {
/* main is an element wrapping the 3 flex items highlighted in the figure above */
main {
display: flex;
flex-direction: row;
}
.navigation {
/*
** flex direction is row, so flex-basis acts like this flex item width
** according to the design, the desired width on foldables / dual-screens is 60px
*/
flex-basis: 60px;
flex-grow: 0;
flex-shrink: 0;
}
.inbox {
/*
** inbox width consumes the entire width of the first display region, ex
** inbox width = display-region-1-width - 60px (navigation column width)
*/
flex-basis: calc( env(fold-left) - 60px );
/*
** some devices have a mask, so we need to add a margin or a gap after this column
** env(fold-width) = 28 CSS-pixels on surface Duo.
** env(fold-width) = 0 CSS-pixels on devices that does not mask content.
*/
margin-inline-end: env(fold-width);
flex-grow: 0;
flex-shrink: 0;
}
.email-content {
/*
** the email content column should "grow" to fill the rest of the space
** but to demonstrate how to calculate the width of the 2nd display region
** we will manually set the width
*/
flex-basis: calc( 100vw - (env(fold-left) + env(fold-width)) );
flex-grow: 0;
flex-shrink: 0;
}
}
在JavaScript中列举窗口段
当使用Canvas2d或WebGL等非DOM目标时,你可以使用新的Window Segments Enumeration API获得每个显示区域的几何图形。
getWindowSegments()是Window对象的一个方法,它返回一个由1个或多个DOMRects组成的数组,代表每个显示区域的几何形状和位置。
返回的数组是在调用该方法时显示区域状态的不可改变的快照。如果用户从跨度状态过渡到非跨度状态,或者旋转设备,那么之前检索到的窗口段就会失效。
const segments = window.getWindowSegments();
// case 1: desktops, traditional touch screen devices, foldable device not spanned
console.log(segments.length) // 1
// case 2: dual-screen and foldable
console.log(segments.length) // 2
页面应该监听窗口大小调整事件或方向改变事件,以检测浏览器是否被调整大小,或设备是否被旋转,并检索更新的显示区域。
let segments = window.getWindowSegments();
// state 1: browser is spanned across 2 displays and fold is vertical.
console.log(segments.length); // 2
// state 2: user decided to rotate the device, browser is still spanned but fold is now *horizontal*
// on window resize, both resize and orientationchange events fire
// resize events will also fire when user go in or out of spanned state.
window.addEventListener('resize', () => {
// segments we initially retrieved are no longer
// update with latest information representing segments the 2 when the fold is horizontal
segments = window.getWindowSegments();
});
没有明确的方法来了解折叠姿势是垂直还是水平的,因为这个信息可以很容易地从返回的DOMRects中计算出来。
function isSingleFoldHorizontal() {
const segments = window.getWindowSegments();
// single fold means the device has 1 fold and 2 display regions
if( segments.length !== 2 ) {
return false;
}
// horizontal fold means 1st segment top is smaller than 2nd segment top
if( segments[0].top < segments[1].top ) {
return true;
}
// if we reach this point, the fold is vertical
return false;
}
折叠宽度也是如此,网页开发者可以使用getWindowSegments()提供的信息来了解窗口管理器是否屏蔽了折叠后渲染的内容,以及折叠宽度是否大于零像素。
function foldWidth() {
const segments = window.getWindowSegments();
// if there's 1 segment, fold mask is not applicable, return 0
// if there's more than 2 segments, we don't deal with this kind of device, yet, return 0
if( segments.length !== 2 ) {
return 0;
}
// fold is vertical
// device looks like this: [][]
if( segments[0].top === segments[1].top ) {
return segments[1].left - segments[0].right;
}
// if we reach this point, the fold is horizontal
return segments[1].top - segments[0].bottom;
}
面向未来
作为开发者,我们倾向于在为今天创造时为未来做打算,所以需要进行最低限度的重构,以解锁未来可能出现的场景。
一个想象中的有2个折页和3个屏幕的设备
与CSS不同,JavaScript有数组、循环和条件的概念,这使得Window Segments Enumeration API和一个有N个显示区域的设备之间的映射更加直接。对于上面的假想设备,当浏览器跨越所有3个显示区域时,调用getWindowSegments()方法将返回一个包含3个DOMRects的数组,使用简单的语言原语,如循环或内置数组方法,你可以了解更多关于显示区域是如何配置的(例如,所有屏幕都是相同宽度的吗,等等。
在CSS中,目前的计划是简单地向代表新屏幕拓扑结构的跨屏媒体功能添加新值。
今天就开始增强你的网站的可折叠体验
CSS跨屏媒体功能和窗口段列举API在一个实验性标志后面可用,你可以在edge://flags/#enable-experimental-web-platform-features启用它们。
从微软Edge 86开始,网络开发者可以使用微软Edge DevTools来模拟Windows和Mac桌面平台上的双屏和可折叠设备。另外,你可以下载并安装新的Surface Duo模拟器预览版(2020.806.1版或更新版),在启用实验性平台功能标志后,使用内置的Edge浏览器进行测试和调试。
JavaScript窗口段列举API和CSS跨屏媒体功能都可以作为Origin试用版使用,你可以获得代币,在生产中安全地试验这些新的基元,以换取向我们提供关于API的反馈。如果您对测试这些API感兴趣,请报名参加Origin试用。
未来之路
在Chromium项目、谷歌、英特尔、W3C的CSSWG、Second-screen WG和其他许多人的合作下,经过多次迭代和改进,这些API今天可以供你试验。
我们已经为Chromium开源项目贡献了桌面平台的CSS和JavaScript基元,现在DevTools的可折叠和双屏设备仿真不仅可以在Edge中使用,也可以在Chrome中使用,不久还可以在其他基于Chromium的浏览器中使用。我们目前正在努力将安卓系统的实现推向上游,以便安卓系统上所有基于Chromium的浏览器都能支持网络开发者为这种灵活的设备类别提供令人兴奋的新体验。
如果你对其中任何一个API有反馈,请在GitHub上开一个问题让我们知道,或者你也可以在Twitter上联系我们(@_zouhir 或@MSEdgeDev)。
- Zouhir Chahoud, 项目经理
- Daniel Libby, 首席软件工程经理