当前位置: 首页 > 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命…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现

目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

ES6从入门到精通:前言

ES6简介 ES6&#xff08;ECMAScript 2015&#xff09;是JavaScript语言的重大更新&#xff0c;引入了许多新特性&#xff0c;包括语法糖、新数据类型、模块化支持等&#xff0c;显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var&#xf…...

Spark 之 入门讲解详细版(1)

1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室&#xff08;Algorithms, Machines, and People Lab&#xff09;开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目&#xff0c;8个月后成为Apache顶级项目&#xff0c;速度之快足见过人之处&…...

【Oracle APEX开发小技巧12】

有如下需求&#xff1a; 有一个问题反馈页面&#xff0c;要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据&#xff0c;方便管理员及时处理反馈。 我的方法&#xff1a;直接将逻辑写在SQL中&#xff0c;这样可以直接在页面展示 完整代码&#xff1a; SELECTSF.FE…...

反射获取方法和属性

Java反射获取方法 在Java中&#xff0c;反射&#xff08;Reflection&#xff09;是一种强大的机制&#xff0c;允许程序在运行时访问和操作类的内部属性和方法。通过反射&#xff0c;可以动态地创建对象、调用方法、改变属性值&#xff0c;这在很多Java框架中如Spring和Hiberna…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版

7种色调职场工作汇报PPT&#xff0c;橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版&#xff1a;职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...

PAN/FPN

import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?

在工业自动化持续演进的今天&#xff0c;通信网络的角色正变得愈发关键。 2025年6月6日&#xff0c;为期三天的华南国际工业博览会在深圳国际会展中心&#xff08;宝安&#xff09;圆满落幕。作为国内工业通信领域的技术型企业&#xff0c;光路科技&#xff08;Fiberroad&…...

【C++】纯虚函数类外可以写实现吗?

1. 答案 先说答案&#xff0c;可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...