CSS魔术师Houdini,用浏览器引擎实现高级CSS效果
开门见山,直接上货
🔍 CSS Houdini是什么?
“Houdini”一词引用自“Harry Houdini”,他是一位20世纪的著名魔术师,亦被称为史上最伟大的魔术师、逃脱术师及特级表演者。
我们都知道,浏览器在渲染网页显示样式的时候,浏览器的渲染引擎会对 CSSOM 进行解析——包括布局、绘制和合成过程。而本文要讲的内容
Houdini
是一组公开 CSS 引擎部分的底层API
,它可以让开发者能够人工干预浏览器的渲染进程,Houdini
的核心APIPainting 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-image
、border-image
、list-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使用方法很简单,我总结为有以下几个步骤,我以实现一个波浪线来进行演示(最终效果如下图):
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
兼容性还不是很好,使用时注意判断浏览器是否支持。
🎨 Houdini 案例
以下网站有一些很有意思的 Houdini Demo,感兴趣的可以看下:
https://houdini.how/
思考:因为利用 paint 绘制图案是静态单次绘制,没有办法只通过工作集来实现连续的动画过程,但是可以配合animation进行多次渲染,尤其是 steps 逐帧动画,配合 Houdini ,可以创造很多有意思的动画,例如steps配合 paint 绘制时钟(注意paint的ctx对象不支持绘制文本)。
最后
我是喜欢归纳总结前端相关知识的前端阿彬,尽力持续输出原创优质文章,欢迎点赞关注😘
往期文章:
# ☕ 通过和vue语法逐一比对,快速上手前端框架黑马svelte
# 🧙♀️css魔法:伪元素content ➕ css函数
# 玩转css逐帧动画,纯css让哥哥动起来💃
# 🕸2023 前端 SEO 无死角解读
# 我给自己搭建的前端导航网站,你们都别用🤪
# 2023 最新最细 vite+vue3+ts 多页面项目架构,建议收藏备用!
# 浅谈 强制缓存/协商缓存 怎么用?
# 2023 前端性能优化清单
相关文章:

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

DC/DC开关电源学习笔记(二)开关电源的分类
(二)开关电源的分类 1.DC/DC类开关电源2.AC/DC变换器3.电路结构分类4.功率开关管分类5.电路拓扑分类 根据变换方式,电源产品有下列四大类; (1):第一大类:AC/DC开关电源; …...

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 数据库,是一个基于分布式文件存储的开源的非关系型数据库系统,其内容是以 K/V 形式存储,结构不固定,它的字段值可以包含其他文档、数组和文档数组等。其采用的 BSON(二进制 JSON &am…...

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

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

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…...

leecode 数据库:1158. 市场分析 I
数据导入: SQL Schema: 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地址检测同一局域网,多台主机存活情况检测同一局域网,多台主机存活情况多线程检测主机存活情况 while循环case选择语…...

汽车售后接待vr虚拟仿真实操演练作为岗位培训的重要工具和手段
汽车虚拟仿真教学软件是一种基于虚拟现实技术的教学辅助工具。它能够模拟真实的汽车环境和操作场景,让学生能够通过虚拟仿真来学习和实践汽车相关知识和技能。与传统的教学方式相比,汽车虚拟仿真教学软件具有更高的视觉沉浸感和互动性,能够更…...

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

Vue3列表竖向滚动(包含使用swiper的翻页效果)
一、使用element-plus表格进行滚动: 可以满足的需求:表格一行一行竖向滚动,类似走马灯。 不能满足的需求:表格分页竖向滚动,有翻页的效果。 代码: <template><el-table:data"tableData"…...

OS 死锁处理
如果P先申请mutex 则mutex从1置零,假设申请到的empty 0则empty变成-1阻塞态 同理C中mutex从0变为-1,那么如果想离开阻塞态,那么就需要执行V(empty)但是如果执行V(empty)就需要P(mu…...

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

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

【若依框架RuoYi-Vue-Plus 图片回显不显示问题,OSS文件上传或者本地上传】
一、问题 1.设计表 product(商品表) 有 id (id) name(商品名)icon(图标) 2.使用若依代码生成功能,导入product表,代码生成。 3.将生成的代码导入到项目中得到…...

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

uwsgi部署多进程django apscheduler与问题排查
💖 作者简介:大家好,我是Zeeland,开源建设者与全栈领域优质创作者。📝 CSDN主页:Zeeland🔥📣 我的博客:Zeeland📚 Github主页: Undertone0809 (Zeeland)&…...

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

Java设计模式:一、六大设计原则-05:接口隔离原则
文章目录 一、定义:接口隔离原则二、模拟场景:接口隔离原则三、违背方案:接口隔离原则3.1 工程结构3.2 英雄技能调用3.2.1 英雄技能接口3.2.2 英雄:后裔3.2.3 英雄:廉颇 3.3 单元测试 四、改善代码:接口隔离…...

第63步 深度学习图像识别:多分类建模误判病例分析(Tensorflow)
基于WIN10的64位系统演示 一、写在前面 上两期我们基于TensorFlow和Pytorch环境做了图像识别的多分类任务建模。这一期我们做误判病例分析,分两节介绍,分别基于TensorFlow和Pytorch环境的建模和分析。 本期以健康组、肺结核组、COVID-19组、细菌性&am…...

OpenCv读/写视频色差 方案
OpenCv read / write video color differenceOpenCv读/写视频色差 感谢博主: OpenCv读/写视频色差答案 - 爱码网 有没有办法让 OpenCV 使用正确的转换?? 是的,使用 GStreamer 后端而不是 FFmpeg 后端,颜色看起来很完…...

【传输层】网络基础 -- UDP协议 | TCP协议
再谈端口号端口号范围划分netstatpidof UDPUDP的特点面向数据报UDP的缓冲区 基于UDP的应用层协议 TCP认识TCP协议的报头理解封装解包理解可靠性TCP工作模式16位窗口大小6位标志位URGACKPSHRSTSYNFIN 再谈端口号 端口号(Port)标识了一个主机上进行通信的不同的应用程序 在TCP/I…...

Android开发之性能测试工具Profiler
前言 性能优化问题,在我们开发时都会遇到,但是在小厂和对自己要求不严格的情况下,我都很少去做性能优化; 在性能优化上,基本大家都是通过自己的开发经验和性能分析工具来发现问题,今天给大家分享一下小编最…...

SpringBoot初级开发--多环境配置的集成(9)
在Springboot的开发中,我们经常要切换各种各样的环境配置,比如现在是开发环境,然后又切换到生产环境,这个时候用多环境配置就是一个明智的选择。接下来我们沿用上一章的工程来配置多环境配置工程。 1.准备多环境配置文件 这里我…...

(数学) 剑指 Offer 39. 数组中出现次数超过一半的数字 ——【Leetcode每日一题】
❓ 剑指 Offer 39. 数组中出现次数超过一半的数字 难度:简单 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。 你可以假设数组是非空的,并且给定的数组总是存在多数元素。 示例 1: 输入: [1, 2, 3, 2, 2, 2, 5, 4, 2] 输…...

如何用PS把roughness贴图转换成Smoothness,并放入Metallic贴图的a通道。
1:用PS打开Roughness贴图 2:选择反相,装换成Smoothness贴图 3:新建一个大小相等的psd文件,或者打开Metallic贴图 4:如果没有金属度贴图,就把新建的图画成纯黑色 5:选择图层蒙版->…...

了解XSS攻击与CSRF攻击
什么是XSS攻击 XSS(Cross-Site Scripting,跨站脚本攻击)是一种常见的网络安全漏洞,它允许攻击者在受害者的浏览器上执行恶意脚本。这种攻击通常发生在 web 应用程序中,攻击者通过注入恶意脚本来利用用户对网站的信任&…...

安全测试-django防御安全策略
django安全性 django针对安全方面有一些处理,学习如何进行处理设置,也有利于学习安全测试知识。 CSRF 跨站点请求伪造(Cross-Site Request Forgery,CSRF)是一种网络攻击方式,攻击者欺骗用户在自己访问的网…...