朋友们,美好的一天!什么是Houdini?
Houdini(Houdini)-浏览器API的集合,可以显着改善Web开发过程,包括CSS标准的开发。开发人员将能够使用JavaScript扩展CSS,从而影响CSS渲染并告诉浏览器应如何应用样式。与使用多聚体相比,这将显着提高性能和稳定性。Houdini由两个API组组成-高级API和低级API。高级API与呈现过程(样式-布局-绘图-合成)相关联。该组包括:- Paint API-允许您在渲染视觉元素(颜色,背景,边框等)的步骤(即渲染阶段)扩展CSS。
- 布局API-允许您在确定元素的大小,位置和对齐方式的步骤中扩展CSS。
- 动画API-显示和设置元素动画的步骤中的“扩展点”。
低级API是高级API的基础,包括:- 类型对象模型API
- 自定义属性和值API
- 字体指标API
- 工作台
CSS的未来
Houdini与常规CSS不同,它允许开发人员以更自然的方式扩展CSS。这是否意味着CSS规范将停止发展并采用新的标准?一点也不。Houdini的目标是通过创建可以轻松标准化的工作原型来帮助开发CSS新功能。此外,开发人员可以轻松共享打开的CSS工作集,而无需担心兼容性。类型对象模型(TOM)API
在Houdini之前,JS和CSS交互的唯一方法是将CSS转换为字符串并对其进行修改。由于需要对值类型进行两次转换(例如,从数字到字符串,反之亦然),因此手动解析和重新定义样式可能很复杂且容易出错。您还必须手动指定新值的度量单位。selectedElement.style.fontSize = newFontSize + 'px'
console.log(selectedElement.style.fontSize)
通过将CSS属性表示为类型化的JS对象,TOM为CSS属性赋予了更多语义含义。这大大提高了性能,稳定性并促进了代码支持。CSS值由CSSUnitValue接口表示,该接口由值和``度量单位''属性组成。{
value: 20,
unit: 'px'
}
该界面可用于以下新功能:- computeStyleMap():用于解析计算(非内置)样式。在解析或使用其他方法之前,将调用此方法。
- attributeStyleMap:用于解析和修改内联样式。这是一个项目属性。
selectedElement.computedStyleMap().get('font-size')
selectedElement.attributeStyleMap.set('font-size', CSS.em(2))
selectedElement. attributeStyleMap.set('color', 'blue')
selectedElement.computedStyleMap().get('font-size')
selectedElement.attributeStyleMap.get('font-size')
请注意分配新值时如何使用CSS类型。使用此语法可以避免与类型相关的问题,并且生成的代码变得更加安全。正在考虑的API不仅包括get和set,还包括其他方法,例如:- 清除:删除所有内联样式
- delete:删除特定的CSS属性及其值
- 具有:根据指定属性的可用性返回true / false
- append:向支持多个值的属性添加额外的值
检测
let selectedElement = document.getElementById('example')
if(selectedElement.attributeStyleMap){
}
if(selectedElement.computedStyleMap){
}
规格状态
工作草案:发布以供社区讨论。支持
自定义属性和值API
该API允许开发人员通过定义类型,初始值和继承来扩展CSS变量。为了定义自定义属性,必须使用registerProperty方法注册它。此方法确定浏览器应如何应用属性和处理错误。CSS.registerProperty({
name: '--colorPrimary',
syntax: '<color>',
inherits: false,
initialValue: 'blue',
})
具有以下属性的对象将作为参数传递给此方法:- 名称:自定义属性的名称
- 语法:解析指令。预定义值是:<颜色>,<整数>,<数字>,<长度>,<百分比>等。
- initialValue:默认值(覆盖之前以及发生错误时)
在上面的示例中,定义了<color>类型的自定义属性。此属性将用于确定渐变。常规CSS不支持渐变过渡。注意,如何使用custom属性定义过渡。.gradient-box {
background: linear-gradient(45deg, rgba(255, 255, 255, 1) 0% var(--colorPrimary) 60%);
transition: --colorPrimary 0.5s ease;
...
}
.gradient-box:hover {
--colorPrimary: red;
...
}
浏览器不知道如何进行渐变过渡,但知道如何进行颜色过渡。这就是为什么我们将属性类型定义为<color>的原因。在支持Houdini的浏览器中,将鼠标悬停时将发生渐变更改。也可以使用CSS自定义属性(注册为<percentage>)来更改以百分比为单位的渐变位置。将来可能会在CSS中直接注册自定义属性。@property --colorPrimary {
syntax: '<color>';
inherits: false;
initial-value: blue;
}
例
这个简单的示例说明了如何使用自定义CSS属性更改渐变的颜色和控制点。可以在此处找到示例代码。
检测
if(CSS.registeredProperty) {
}
规格状态
工作草案:发布以供社区讨论。支持
字体指标API
该API处于开发的早期阶段,因此该规范将来可能会发生巨大变化。当前,它提供了用于测量屏幕上显示的文本元素大小的方法,从而允许开发人员影响字符的呈现。现有的CSS功能不允许您使用这些值或使这项工作非常困难。使用此API的一个示例是文本的多行动态截断。规格状态
意见征集:草稿未发表。不支持浏览器。Vorkleta
在继续使用以下API之前,您需要了解Worklet的概念。Vorklet是在渲染期间运行的脚本,并且独立于基础JS代码。它们扩展了渲染引擎的功能,专为并行执行(2个或更多实例)而设计,不阻塞主线程,对全局范围的访问受限,并且在必要时由引擎调用。Vorklet只能通过HTTPS(生产环境)或localhost(出于开发和测试目的)运行。Houdini包含以下扩展浏览器呈现引擎的工作集:- Paint Worklet-Paint API
- 动画作品-动画API
- 布局工作簿-布局API
绘画API
Paint API允许开发人员使用JS函数通过2D渲染上下文(它是HTML5 Canvas API的子集)来绘制元素的背景,边框或内容。Paint API使用Paint Worklet绘制图像,该图像取决于CSS的更改(例如CSS变量的更改)。那些熟悉Canvas API的人将会对Paint API感到宾至如归。创建Paint Worklet包含几个步骤:- 使用registerPaint函数编写和注册工作集
- 使用CSS.paintWorklet.addModule调用HTML或JS中的工作表
- 在CSS中使用paint()方法以及vorklet的名称和传递的参数
让我们看一下registerPaint函数,该函数用于注册和确定Paint Worklet的功能。registerPaint('paintWorkletExample', class {
static get inputProperties() { return ['--myVariable']; }
static get inputArguments() { return ['<color>']; }
static get contextOptions() { return {alpha: true} }
paint(ctx, size, properties, args) {
}
})
registerPaint函数由以下部分组成:- inputProperties:工作项正在观察的自定义CSS属性的数组。该数组表示工作项的依赖关系
- inputArguments:可以从函数传递到外部CSS的参数数组
- contextOptions:颜色透明度。如果为假,则所有颜色将完全不透明
- paint:主要功能,采用以下参数:
- ctx:2D绘图上下文,几乎与Canvas API的2D画布上下文相同
- size:具有元素宽度和高度的对象。值取决于布局渲染过程。画布大小与实际商品大小相同
- 属性:inputProperties中包含的变量
- args:传递给paint函数的参数数组
注册工作文件后,必须以HTML调用它,指示文件的路径。CSS.paintWorklet.addModule('path/to/worklet/file.js')
可以从任何外部来源(例如,从CDN)添加Vorklet,这使其成为模块化且可重复使用。CSS.paintWorklet.addModule('https://url/to/worklet/file.js')
调用工作件后,可以使用“ paint”功能在CSS中使用它。此函数作为第一个参数,采用vorklet的注册名称以及在inputArguments中指定的所有参数。从这一刻起,浏览器就知道何时调用工作集以及哪些用户操作导致CSS自定义属性的某些值发生更改。.example-element {
background: paint(paintWorkletExample, blue);
}
例
下面的示例演示了Paint API的用法以及工作集的模块化和重用。它使用Google Chrome Labs存储库中的涟漪工作表。在这里查看示例代码。
检测
if(‘paintWorklet’ in CSS){
}
@supports(background: paint(paintWorkletExample)){
}
规格状态
建议:稳定的工作草案,随时可用。支持
动画API
该API通过处理各种事件(滚动,悬停,单击等)扩展了Web动画,并通过动画工作集以自己的流形式启动动画来提高性能。像其他任何工作区一样,必须首先注册锻炼动画。registerAnimation(‘animationWorkletExample’, class {
constructor(options){
}
animate(currentTime, effect){
}
})
此类包含两个功能:- 构造函数:在创建新实例时调用。用于常规设置。
- 动画:包含动画逻辑的主要功能。接受以下参数:
- currentTime:特定时间轴上的时间戳
- 效果:动画中使用的一系列效果
注册后,该工作集将包含在主JS文件中,并添加了动画(元素,框架,设置)并将其附加到时间轴上。下一节将介绍时间轴标记的概念和网络动画的基础。
await CSS.animationWorklet.addModule(‘path/to/worklet/file.js’)
const elementExample = document.getElementById(‘element-example’)
const effectExample = new KeyframeEffect(
elementExample,
[
{
)
new WorkletAnimation(
‘animationWorkletExample’
effectExample,
document.timeline,
{},
).play()
时标
Web动画基于时间戳-动画时间表上效果的里程碑。例如,我们分析了一个重复的线性动画,该动画由三个帧(开始,中间,结尾)组成,在页面完全加载(延迟)后1秒开始,持续4秒。效果的时间戳将如下所示(对于持续4秒且没有延迟的动画):值为3000ms(给定延迟为1000ms)的effect.localTime会将动画绑定到时间轴上的平均帧(1000ms延迟+ 2000ms平均帧)。设置7000ms和11000ms时将获得相同的效果,因为动画每4000ms重复一次。animate(currentTime, effect){
effect.localTime = 3000
}
使用effect.localTime的恒定值,动画将锁定在特定帧上。因此,effect.localTime的值应更改。该值应该是绑定到currentTime或另一个变量的函数。线性动画代码如下所示:animate(currentTime, effect){
effect.localTime = currentTime
}
时间戳不限于1:1。动画API允许开发人员使用标准JS函数创建复杂的效果,通过动画函数来操纵标记。动画也可以在每次迭代中变化(具有可重复的动画)。动画不仅可以与文档加载相关联,还可以与用户操作相关联。可以通过ScrollTimeline对象在动画中使用诸如滚动页面之类的用户操作。例如,动画可以在滚动200像素时开始,而在滚动800像素时结束。const scrollTimelineExample = new ScrollTimeline({
scrollSource: scrollElement,
orientation: ‘vertical’,
startScrollOffset: ‘200px’,
endScrollOffset: ‘800px’,
timeRange: 1200,
fill: ‘forwards’
})
动画会自动适应滚动速度,同时保持平滑和响应。由于动画在其自己的流中运行并连接到浏览器渲染引擎,因此动画可以平稳启动并且不会影响性能。例
下面的示例演示非线性动画。它使用高斯函数,并在此前后同时旋转。在这里查看示例代码。
检测
if(CSS.animationWorklet){
}
规格状态
第一份公共工作草案:准备进行社区讨论,将来可能会发生变化。支持
布局API
Layout API允许开发人员通过定义要在CSS“ display”属性中使用的新模块来扩展布局渲染过程。该API引入了新概念,非常复杂,并且提供了大量设置来开发用于处理页面布局的自定义算法。首先,需要注册一个Worklet。registerLayout(‘exampleLayout’, class{
static get inputProperties() { return [‘--example-variable’] }
static get childrenInputProperties() { return [‘--exampleChildVariable’] }
static get layoutOptions(){
return {
childDisplay: ‘normal’,
sizing: ‘block-like’
}
}
intrinsicSizes(children, edges, styleMap){
}
layout(children, edges, constraints, styleMap, breakToken){
}
})
注册工作簿包括以下方法:- inputProperties:工作集正在观察并属于父级的自定义CSS属性的数组,父属性是导致布局呈现的元素。此数组表示布局依赖性
- childrenInputProperties:小部件监视的属于后代的自定义CSS属性的数组
- layoutOptions:定义以下布局属性:
- childDisplay:预定义的值是block和normal。定义项目的显示方式(块或行)
- 大小:预定义值是块状和手动的。确定是否需要初步计算元素大小(如果未指定)
- nativeSizes:定义如何在布局上下文中显示容器或其内容:
- children:导致页面布局呈现的元素的子元素
- 边缘:容器边界
- styleMap:键入的容器样式对象模型
- layout:使用布局的主要功能:
- 子元素:子元素
- 边缘:边框
- 约束:父布局施加的约束
- styleMap:键入的容器样式对象模型
- breakToken:分页或打印布局拆分的断点
接下来,将工作项添加到HTML或JS文件。CSS.layoutWorklet.addModule(‘path/to/worklet/file.js’)
我们用样式链接到文件中的工作项。.example-element {
display: layout(exampleLayout)
}
布局API如何与布局一起使用
在前面的示例中,我们定义了exampleLayout。.example-element称为父级布局,包括缩进,边框和滚动滑块。父布局由称为当前布局的子元素组成。当前布局是目标元素,其布局是使用Layout API“自定义”的。例如,当使用“ display:flex”时,元素的后代会根据灵活的布局进行重新排列。这类似于Layout API的操作。当前的每个布局都包含子布局,这些子布局包含用于渲染子元素LayoutChild的算法(包括伪类:: before和:: after)。LayoutChild-由CSS生成的容器,其中包含样式数据(不包含布局数据)。浏览器会在应用样式阶段自动创建LayoutChild元素。子布局可以创建一个Fragment,其中包含用于渲染布局的指令。例
此示例还使用了Google Chrome Labs存储库,但是文本被替换为图像。在这里查看示例代码。
检测
if(CSS.layoutWorklet){
}
规格状态
第一份公共工作草案:准备进行社区讨论,将来可能会发生变化。支持
胡迪尼和不断进步
尽管Houdini当前没有最佳的浏览器支持,但可以将其用于逐步改进。如果您不熟悉渐进式改进的概念,建议您阅读本文。使用Houdini时,应考虑以下几点:始终确定支持以避免错误。
每个Houdini API和Worklet都有一种检查可用性的简便方法。这样可以避免在尚不支持该技术的浏览器中使用Houdini的问题。使用Houdini改善显示和可视化效果。
使用不支持Houdini的浏览器的用户应有权访问该网站的内容和基本功能。用户体验和内容显示不应依赖Houdini。使用标准CSS作为替代
例如,自定义CSS属性可以用作自定义属性和值API的替代方法。专注于开发生产和可靠的应用程序,将Houdini用于装饰目的只是一种渐进的改进。结论
Houdini允许开发人员在渲染过程中使用JS代码处理样式,从而提高应用程序性能和稳定性。在呈现过程中嵌入代码的功能使您可以创建易于与他人共享,应用甚至可能包含在规范中的CSS多义词。此外,Houdini允许开发人员和设计人员在使用样式,布局和动画时减少对CSS限制的依赖。Houdini现在可以使用,但只能作为逐步的改进。这将允许不支持Houdini的浏览器显示页面而不会出现错误,从而提供最佳的用户体验。我等不及开发人员社区才能充分享受Houdini的功能。以下是几个示例:CSS Houdini过期CSS Houdini交互式介绍HoudiniGoogle Chrome实验室的示例参考文献
HoudiniHoudini 规范的W3C草案(Chrome Dev Summit 2018)动画工作集-Google Developers感谢您的关注。