当前位置: 首页 > news >正文

CSS魔术师Houdini,用浏览器引擎实现高级CSS效果

fbce5e79f3a74987b5dc1cd239a52e52.png

开门见山,直接上货

🔍 CSS Houdini是什么?

“Houdini”一词引用自“Harry Houdini”,他是一位20世纪的著名魔术师,亦被称为史上最伟大的魔术师、逃脱术师及特级表演者。

我们都知道,浏览器在渲染网页显示样式的时候,浏览器的渲染引擎会对 CSSOM 进行解析——包括布局、绘制和合成过程。而本文要讲的内容 Houdini一组公开 CSS 引擎部分的底层API,它可以让开发者能够人工干预浏览器的渲染进程,Houdini的核心API Painting API就是将我们自定义的js代码插入到浏览器的绘制环节。

Houdini包括以下 API >>>

  • CSS Properties and Values API:顾名思义,就是与css属性相关的一系列 API,用于注册新的 CSS 属性,包括CSS.registerProperty API 和@property关键词(它们俩是等价的),例如我们常用 @property 常用于定义新的css属性,以实现一些css属性的动画过程,例如背景渐变色的变化过程。

  • CSS Typed OM:我们经常使用dom对象的style属性获取/设置它的一些 css 属性值,操作的值都是字符串。而 CSS Typed OM API为我们提供了一些列方法,可以获取/设置具体的css属性值、单位,(你可能觉得它很鸡肋,但是它也有它的优势,例如不用考虑属性的写法、强大的数学操作和单位转换、错误捕获处理、性能更好。

  • CSS Painting API:它可以说是CSS Houdini的核心 API之一,它其实就是css界的canvas,实现给元素设置复杂的自定义背景。使用时像 CSS.registerProperty 注册一个画像,然后就可以把这个画像应用于任何可以设置image的css属性上,例如background-imageborder-imagelist-style-image等。

  • Worklets工作集也是CSS Houdini的核心 API之一。它用于在独立于主要 JavaScript 执行环境的渲染管道的各个阶段运行脚本的 API。它相当于 Web Workers 渲染管道的轻量级版本。它只有一个实例方法Worklet.addModule(),用于将给定 URL 处的脚本模块添加到当前工作集。注册工作集后,你可以像任何其他值一样在 CSS 中使用它。

  • CSS Layout API、CSS Parser API、Font Metrics API:最后这三个 API目前浏览器支持性都几乎为零,所以本文就不做介绍了。

☕ CSS Houdini怎么用?

CSS Houdini使用方法很简单,我总结为有以下几个步骤,我以实现一个波浪线来进行演示(最终效果如下图):

image.png

1. 创建工作集文件

首先我们需要创建一个js文件,我这里取名为curved-line.js,我们要在里面实现自定义的背景效果。

2.使用registerPaint注册工作集

在我们创建的curved-line.js文件中添加以下代码注册工作集:
registerPaint有两个参数:registerPaint(name, classRef),如下代码:

//实现工作集的类的引用。
class CurvedLine {//实现自定义css效果的代码
}//注册Worklets工作集  "curved-line": 要注册的工作集类的名称
registerPaint("curved-line", CurvedLine);

3.在工作集类中实现炫酷效果

绘图工作集类我们需要关注以下 4 个函数:

  • contextOptions:该函数定义了一个上下文选项contextOptions(),如下面的例子中返回一个简单的对象,声明允许 alpha 透明度;
  • inputProperties,要使用哪些CSS自定义属性(只能使用var变量,不可以使用css内置属性);
  • inputArguments,CSS中使用paint函数除了模块名外的其他参数,指定其类型;
  • paint:最关键的方法,定义绘制行为。ctx的使用和canvas一致,size表示绘制的大小,包括width、height等信息,properties就是inputProperties静态方法里定义的属性,args就是paint的入参,跟inputArguments定义的对应。

下面是这 4 个方法的使用示例:

//file.js  工作集类方法示例
registerPaint('paint-color-example', class {  static get inputProperties() {   return ['--my-color'];  }  static get inputArguments() {   return [''];  }  static get contextOptions() {   return {alpha: true};  }  paint(ctx, size, properties, args) {  ctx.fillStyle = properties.get('--my-color');  ctx.beginPath();  ...  
});

以下是绘制曲线的代码(不多说了,就是用canvas绘制曲线):

// curved-line.js
if (typeof registerPaint !== "undefined") {class CurvedLine {static get inputProperties() {return ["--curved-lineColor","--curved-lineSpread","--curved-lineWidth","--curved-lineHeight",];}paint(ctx, size, properties) {const lineWidth = parseInt(properties.get('--curved-lineWidth')) || 3;const lineHeight = parseInt(properties.get('--curved-lineHeight')) || size.height;const color = String(properties.get('--curved-lineColor')) || 'black';const spread = parseInt(properties.get('--curved-lineSpread')) || 50;const offset = (lineHeight < size.height) ? (size.height - lineHeight) / 2 : 0;const midPoint = lineHeight / 2;ctx.lineWidth = lineWidth;ctx.strokeStyle = color;ctx.beginPath();ctx.moveTo(0, midPoint + offset);let curStep = spread;while (curStep < size.width + spread) {const cp1x = curStep;const cp1y = (lineHeight * 1.5) + offset;const cp2x = curStep + spread;const cp2y = 0 - midPoint + offset;const x = curStep + spread * 2;const y = midPoint + offset;ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);curStep = curStep + (spread * 3);}ctx.stroke();}}registerPaint("curved-line", CurvedLine);
}

4. 将自定义的工作集添加到当前工作集

你要知道想要实现 CSS Houdini,即从原生层面扩展 CSS,就必须要以Worklets工作集的方式将自定义css的代码注册到渲染引擎的进程中。上面我们也提到了Worklets的使用方法:使用 Worklet.addModule() 实例方法将指定 URL 处的脚本模块添加到当前工作集,如下:

需要注意的是:

  • Worklets可以使用的类有很多种,例如网络音频工作集AudioWorklet,高性能程序动画工作集AnimationWorklet,绘图工作集PaintWorklet等,我们这里只使用了 PaintWorklet;
  • 工作集必须是个单独的js文件,并通过 Worklet.addModule() 引入;
  • Worklet 允许ESM静态导入,即使用import导入,但是不支持import()动态导入,会抛出异常!

在index.html或者main.js中添加我们的工作集:

<script>CSS.paintWorklet.addModule("curved-line.js");
</script>

5. 使用paint()函数设置炫酷背景

.line{width: 400px;height: 200px;--curved-lineHeight:20;--curved-lineWidth:4;--curved-lineColor: green;--curved-lineSpread:15;background: paint(curved-line);
}<div class="line"></div>

大功告成~~~🎉🎉🎉

🍭 CSS Houdini 的优点

以往我们实现复杂的效果往往都需要使用js和css进行配合,而使用 Houdini 后,相比 JavaScript ,它能够更快的解析。因为 Houdini 的代码不会像js一样等待 cssom 布局绘制完成后然后又可能造成回流重绘,它是被注入到浏览器渲染引擎的渲染进程中的。

在 JavaScript 中键入 CSS 值以及填充或发明新的 CSS 而不会影响性能终于成为可能。Houdini具有增强网络创造力的潜力。

🍭 CSS Houdini 的兼容性

目前 Houdini 的核心 API Painting API 兼容性还不是很好,使用时注意判断浏览器是否支持。

image.png

🎨 Houdini 案例

以下网站有一些很有意思的 Houdini Demo,感兴趣的可以看下:
https://houdini.how/

思考:因为利用 paint 绘制图案是静态单次绘制,没有办法只通过工作集来实现连续的动画过程,但是可以配合animation进行多次渲染,尤其是 steps 逐帧动画,配合 Houdini ,可以创造很多有意思的动画,例如steps配合 paint 绘制时钟(注意paint的ctx对象不支持绘制文本)。

最后

我是喜欢归纳总结前端相关知识的前端阿彬,尽力持续输出原创优质文章,欢迎点赞关注😘

表情包2.webp

往期文章
# ☕ 通过和vue语法逐一比对,快速上手前端框架黑马svelte
# 🧙‍♀️css魔法:伪元素content ➕ css函数
# 玩转css逐帧动画,纯css让哥哥动起来💃
# 🕸2023 前端 SEO 无死角解读
# 我给自己搭建的前端导航网站,你们都别用🤪
# 2023 最新最细 vite+vue3+ts 多页面项目架构,建议收藏备用!
# 浅谈 强制缓存/协商缓存 怎么用?
# 2023 前端性能优化清单

相关文章:

CSS魔术师Houdini,用浏览器引擎实现高级CSS效果

开门见山&#xff0c;直接上货 &#x1f50d; CSS Houdini是什么&#xff1f; “Houdini”一词引用自“Harry Houdini”&#xff0c;他是一位20世纪的著名魔术师&#xff0c;亦被称为史上最伟大的魔术师、逃脱术师及特级表演者。 我们都知道&#xff0c;浏览器在渲染网页显示样…...

DC/DC开关电源学习笔记(二)开关电源的分类

&#xff08;二&#xff09;开关电源的分类 1.DC/DC类开关电源2.AC/DC变换器3.电路结构分类4.功率开关管分类5.电路拓扑分类 根据变换方式&#xff0c;电源产品有下列四大类&#xff1b; &#xff08;1&#xff09;&#xff1a;第一大类&#xff1a;AC/DC开关电源&#xff1b; …...

conda创建python虚拟环境

1.查看当前存在那些虚拟环境 conda env list conda info -e 2.conda安装虚拟环境 conda create -n my_env_name python3.6 2.1在anaconda下改变python版本 当前3.7 安装3.7 conda create -n py37 python3.7 conda activate py37 conda create -n py37 python3.7conda a…...

Python 操作 MongoDB 数据库介绍

MongoDB 是一款面向文档型的 NoSQL 数据库&#xff0c;是一个基于分布式文件存储的开源的非关系型数据库系统&#xff0c;其内容是以 K/V 形式存储&#xff0c;结构不固定&#xff0c;它的字段值可以包含其他文档、数组和文档数组等。其采用的 BSON&#xff08;二进制 JSON &am…...

【ES6】Generator 函数

Generator 函数是 ES6 引入的一种新的函数类型&#xff0c;它既可以生成一个序列&#xff0c;又可以在某个条件下停止执行&#xff0c;并在需要时恢复执行。Generator 函数非常适合处理那些需要按需计算的场景&#xff0c;例如处理大数据、生成随机数等。 Generator 函数的基本…...

「操作系统」1. 基础

前言&#xff1a;操作系统基础八股文 文章目录 一 、操作系统基础1.1 什么是操作系统&#xff1f;1.2 什么是系统调用1.3 什么是中断 &#x1f680; 作者简介&#xff1a;作为某云服务提供商的后端开发人员&#xff0c;我将在这里与大家简要分享一些实用的开发小技巧。在我的职…...

Docker安装Oracl数据库!

安装Docker 查看是否安装docker: yum list installed | grep docker 安装docker: yum -y install docker 启动docker: systemctl start docker 查看docker启劝状态: systemctl status docker 查看docker版本: docker --version 设置docker开机自启动: systemctl en…...

QT子窗口为QWidget类型时,窗口背景不透明的实现方法

1...

leecode 数据库:1158. 市场分析 I

数据导入&#xff1a; SQL Schema&#xff1a; Create table If Not Exists Users (user_id int, join_date date, favorite_brand varchar(10)); Create table If Not Exists Orders (order_id int, order_date date, item_id int, buyer_id int, seller_id int); Create tab…...

简单shell脚本的编写

文章目录 简单使用shell脚本参数判断整数的比较运算符字符串的比较运算shell脚本流程控制shell脚本循环for循环批量添加用户批量ping IP地址检测同一局域网&#xff0c;多台主机存活情况检测同一局域网&#xff0c;多台主机存活情况多线程检测主机存活情况 while循环case选择语…...

汽车售后接待vr虚拟仿真实操演练作为岗位培训的重要工具和手段

汽车虚拟仿真教学软件是一种基于虚拟现实技术的教学辅助工具。它能够模拟真实的汽车环境和操作场景&#xff0c;让学生能够通过虚拟仿真来学习和实践汽车相关知识和技能。与传统的教学方式相比&#xff0c;汽车虚拟仿真教学软件具有更高的视觉沉浸感和互动性&#xff0c;能够更…...

登录校验-Filter-登录校验过滤器

目录 思路 登录校验Filter-流程 步骤 流程图 登录校验Filter-代码 过滤器类 工具类 测试登录 登录接口功能请求 其他接口功能请求 前后端联调 思路 前端访问登录接口&#xff0c;登陆成功后&#xff0c;服务端会生成一个JWT令牌&#xff0c;并返回给前端&#xff0…...

Vue3列表竖向滚动(包含使用swiper的翻页效果)

一、使用element-plus表格进行滚动&#xff1a; 可以满足的需求&#xff1a;表格一行一行竖向滚动&#xff0c;类似走马灯。 不能满足的需求&#xff1a;表格分页竖向滚动&#xff0c;有翻页的效果。 代码&#xff1a; <template><el-table:data"tableData"…...

OS 死锁处理

如果P先申请mutex 则mutex从1置零&#xff0c;假设申请到的empty 0则empty变成-1阻塞态 同理C中mutex从0变为-1&#xff0c;那么如果想离开阻塞态&#xff0c;那么就需要执行V&#xff08;empty&#xff09;但是如果执行V&#xff08;empty&#xff09;就需要P&#xff08;mu…...

Java实现根据按图搜索商品数据,按图搜索获取1688商品详情数据,1688拍立淘接口,1688API接口封装方法

要通过按图搜索1688的API获取商品详情跨境属性数据&#xff0c;您可以使用1688开放平台提供的接口来实现。以下是一种使用Java编程语言实现的示例&#xff0c;展示如何通过1688开放平台API获取商品详情属性数据接口&#xff1a; 首先&#xff0c;确保您已注册成为1688开放平台…...

如何避免重复消费消息

博主介绍&#xff1a;✌全网粉丝3W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…...

【若依框架RuoYi-Vue-Plus 图片回显不显示问题,OSS文件上传或者本地上传】

一、问题 1.设计表 product&#xff08;商品表&#xff09; 有 id &#xff08;id&#xff09; name&#xff08;商品名&#xff09;icon&#xff08;图标&#xff09; 2.使用若依代码生成功能&#xff0c;导入product表&#xff0c;代码生成。 3.将生成的代码导入到项目中得到…...

docker搭建rocketmq环境

准备局域网 nameserver和broker在同一网段才能够互相访问&#xff0c;我们先创建一个局域网。 创建rocketmq-network&#xff0c;让nameserver、broker在同一个网段&#xff1a; docker network create --driverbridge \ --subnet192.168.2.10/24 rocketmq-network安装names…...

uwsgi部署多进程django apscheduler与问题排查

&#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是Zeeland&#xff0c;开源建设者与全栈领域优质创作者。&#x1f4dd; CSDN主页&#xff1a;Zeeland&#x1f525;&#x1f4e3; 我的博客&#xff1a;Zeeland&#x1f4da; Github主页: Undertone0809 (Zeeland)&…...

git difftool对比差异,避免推送不相关内容

问题 在利用git进行版本管理的时候&#xff0c;经常会由于对其他不相关的代码&#xff0c;做了一些小改动&#xff0c;例如删除了一个空行&#xff0c;多了一个缩进等。 为避免将这些不相关的改动也提交到远程&#xff0c;对PR造成不必要的影响&#xff0c;可以利用git diff命…...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻

在如今就业市场竞争日益激烈的背景下&#xff0c;越来越多的求职者将目光投向了日本及中日双语岗位。但是&#xff0c;一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧&#xff1f;面对生疏的日语交流环境&#xff0c;即便提前恶补了…...

【力扣数据库知识手册笔记】索引

索引 索引的优缺点 优点1. 通过创建唯一性索引&#xff0c;可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度&#xff08;创建索引的主要原因&#xff09;。3. 可以加速表和表之间的连接&#xff0c;实现数据的参考完整性。4. 可以在查询过程中&#xff0c;…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望

文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例&#xff1a;使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例&#xff1a;使用OpenAI GPT-3进…...

自然语言处理——循环神经网络

自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元&#xff08;GRU&#xff09;长短期记忆神经网络&#xff08;LSTM&#xff09…...

基于IDIG-GAN的小样本电机轴承故障诊断

目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) ​梯度归一化(Gradient Normalization)​​ (2) ​判别器梯度间隙正则化(Discriminator Gradient Gap Regularization)​​ (3) ​自注意力机制(Self-Attention)​​ 3. 完整损失函数 二…...

【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制

目录 节点的功能承载层&#xff08;GATT/Adv&#xff09;局限性&#xff1a; 拓扑关系定向转发机制定向转发意义 CG 节点的功能 节点的功能由节点支持的特性和功能决定。所有节点都能够发送和接收网格消息。节点还可以选择支持一个或多个附加功能&#xff0c;如 Configuration …...

​​企业大模型服务合规指南:深度解析备案与登记制度​​

伴随AI技术的爆炸式发展&#xff0c;尤其是大模型&#xff08;LLM&#xff09;在各行各业的深度应用和整合&#xff0c;企业利用AI技术提升效率、创新服务的步伐不断加快。无论是像DeepSeek这样的前沿技术提供者&#xff0c;还是积极拥抱AI转型的传统企业&#xff0c;在面向公众…...

React父子组件通信:Props怎么用?如何从父组件向子组件传递数据?

系列回顾&#xff1a; 在上一篇《React核心概念&#xff1a;State是什么&#xff1f;》中&#xff0c;我们学习了如何使用useState让一个组件拥有自己的内部数据&#xff08;State&#xff09;&#xff0c;并通过一个计数器案例&#xff0c;实现了组件的自我更新。这很棒&#…...

深度解析云存储:概念、架构与应用实践

在数据爆炸式增长的时代&#xff0c;传统本地存储因容量限制、管理复杂等问题&#xff0c;已难以满足企业和个人的需求。云存储凭借灵活扩展、便捷访问等特性&#xff0c;成为数据存储领域的主流解决方案。从个人照片备份到企业核心数据管理&#xff0c;云存储正重塑数据存储与…...