CSS Houdini
前言
最近看了几篇文章,是关于 CSS Houdini 的。作为一个前端搬砖的还真不知道这玩意,虽然不知道的东西挺多的,但是这玩意有点高大上啊。
Houdini 是一组底层 API,它们公开了 CSS 引擎的各个部分,从而使开发人员能够通过加入浏览器渲染引擎的样式和布局过程来扩展 CSS。Houdini 是一组 API,它们使开发人员可以直接访问CSS 对象模型 (CSSOM),使开发人员可以编写浏览器可以解析为 CSS 的代码,从而创建新的 CSS 功能,而无需等待它们在浏览器中本地实现。
具体解释见:CSS Houdini
推荐文章
用CSS Houdini画一片星空
CSS Houdini 实现磁吸效果
CSS Houdini:用浏览器引擎实现高级CSS效果
官方案例
Houdini Samples,可以看看有些东西还是很有意思的。
给textarea加一个方格背景
文章中的效果图:

文章中提到了渐变,自己尝试了一下没啥思路。但是有一种取巧的方式——背景图,把下面的图片当成背景图不就好了

textarea{width: 300px;height: 100px;background-image: url('./abc.png');background-size: 80px 40px;color: white;font-size: 30px;}
我的效果,这不是差不多吗😃

突然发现自己有点傻叉,自己这个每一行的颜色都是一样的,跟官方的差远了。
Houdini 基本用法
attributeStyleMap 和 computedStyleMap
- attributeStyleMap 用于处理内联样式,可以进行读写操作
- computedStyleMap 用于处理非内联样式,只允许读
// Before Houdiniconst size = 30
target.style.fontSize = size + 'px' // "20px"const imgUrl = 'https://www.exampe.com/sample.png'
target.style.background = 'url(' + imgUrl + ')' // "url(https://www.exampe.com/sample.png)"target.style.cssText = 'font-size:' + size + 'px; background: url('+ imgUrl +')'
// "font-size:30px; background: url(https://www.exampe.com/sample.png)"
上面的代码应该很多人都写过,拿到dom元素直接修改内联样式。简单的样式这样写还是可以的,但是比较复杂的时候就比较容易出错
这时可以使用 attributeStyleMap 和 computedStyleMap
<template><div id="test">111</div>
</template><script>export default {mounted() {let el = document.getElementById('test');// attributeStyleMap 用于处理内联样式,可以进行读写操作el.attributeStyleMap.set('color', 'blue');el.attributeStyleMap.set('font-size', '40px');console.log(el.attributeStyleMap.get('font-size'), el.attributeStyleMap.get('color'), el.attributeStyleMap.get('width'));// computedStyleMap 用于处理非内联样式,只允许读console.log(el.computedStyleMap().get('color').toString(), el.computedStyleMap().get('font-size'));}
};
</script><style lang="scss" scoped>
#test {width: 100px;height: 100px;background: pink;
}
</style>

自己尝试了一下,有几个需要注意的点:
- attributeStyleMap ,可以进行读写,但是只能读取到内联样式
- computedStyleMap() ,只读,可以读取到dom元素上最终的样式
- 对于有单位的样式,比如
width,会返回一个对象;对于五单位样式,比如color,需要调用toString()方法来进行转换 - 以设置样式来说,不支持链式操作
这里补充一个与computedStyleMap 类似的东西,之前在 css中样式类型及属性值的获取 简单说过,感兴趣的可以看一下
CSS Properties & Values API
可以允许开发者自定义属性和属性值,其实就是css变量。
这个不说了,赶紧用处不大,而且有点习惯使用scss了
Paint API
提供了一组与绘制(Paint)过程相关的API,我们可以通过它自定义的渲染规则,例如调整颜色(color)、边框(border)、背景(background)、形状等绘制规则。
文章最开始介绍的如何实现文本域的背景就是通过这种方式来实现的,通常需要创建一个js来编写绘制逻辑,然后使用registerPaint 进行注册。比如:
/* checkboardWorklet.js */class CheckerboardPainter {paint(ctx, geom, properties) {const colors = ['red', 'green', 'blue'];const size = 32;for(let y = 0; y < geom.height/size; y++) {for(let x = 0; x < geom.width/size; x++) {const color = colors[(x + y) % colors.length];ctx.beginPath();ctx.fillStyle = color;ctx.rect(x * size, y * size, size, size);ctx.fill();}}}
}// 注册checkerboard
registerPaint('checkerboard', CheckerboardPainter);
/* index.html */
<script>CSS.paintWorklet.addModule('path/to/checkboardWorklet.js') // 添加checkboardWorklet到paintWorklet
</script>
/* index.html */
<!doctype html>
<textarea></textarea>
<style>textarea {background-image: paint(checkerboard); // 使用paint()方法调用checkboard绘制背景}
</style>
但是在vue中, CSS.paintWorklet.addModule('path/to/checkboardWorklet.js') 这一步失败了,无法请求的js文件,应该是需要进行设置。
因为不知道如何处理,所以采用第二种方式
示例:绘制一个矩形
// js
let blobURL = URL.createObjectURL(new Blob(['(',function() {class CheckerboardPainter {static get inputProperties() {return ['--rect-color'];}paint(ctx, geom, properties, args) {// ctx 一个 Canvas 的 Context 对象,因此 paint 中的绘制方式跟 canvas 绘制是一样的。// geom 包含节点的尺寸信息,同时也是 canvas 可绘制范围(画板)的尺寸信息。// properties 包含节点的 CSS 属性,需要调用静态方法 inputProperties 声明注入。// CSS 中调用 Paint 类时传入的参数,需要调用静态方法 inputArguments 声明注入const color = properties.get('--rect-color')[0];ctx.fillStyle = color;ctx.fillRect(0, 0, geom.width, geom.height);}}registerPaint('checkerboard', CheckerboardPainter);}.toString(),')()'], { type: 'application/javascript' })
);export default blobURL;// 使用
<template><div><div class="rect"></div></div>
</template><script>import blobURL from './checkerboard.js';
export default {mounted() {CSS.paintWorklet.addModule(blobURL);}
};
</script><style lang="scss" scoped>
.rect {width: 100px;height: 100px;--rect-color: red;background-image: paint(checkerboard);
}
</style>

官方示例文本域
let blobURL = URL.createObjectURL(new Blob(['(',function() {class CheckerboardPainter {paint(ctx, geom, properties, args) {const colors = ['red', 'green', 'blue'];// 方块的尺寸const size = 32;for (let y = 0; y < geom.height / size; y++) {for (let x = 0; x < geom.width / size; x++) {const color = colors[(x + y) % colors.length];ctx.beginPath();ctx.fillStyle = color;ctx.rect(x * size, y * size, size, size);ctx.fill();}}}}registerPaint('checkerboard', CheckerboardPainter);}.toString(),')()'], { type: 'application/javascript' })
);export default blobURL;<template><div><textarea></textarea></div>
</template>
<script>import blobURL from './checkerboard.js';
export default {mounted() {CSS.paintWorklet.addModule(blobURL);}
};
</script><style lang="scss" scoped>
textarea {background-image: paint(checkerboard);
}
</style>

要玩好Paint API,还是需要对canvas非常熟悉才行。
Animation API
提供了一组与合成(composite)渲染相关的API,我们可以通过它调整绘制层级和自定义动画。
略,现在有一些很不错的js动画库,没必要用这个写动画。
Layout API
提供了一组与布局(Layout)过程相关的API,我们可以通过它自定义的布局规则,类似于实现诸如flex、grid等布局,自定义元素或子元素的对齐(alignment)、位置(position)等布局规则。
略,这个一般人玩不了,也没必要看了。
磁吸效果
效果:https://codepen.io/HelKyle/pen/zYWozde
效果图:

let blobURL = URL.createObjectURL(new Blob(['(',function() {class MagnetMatrixPaintWorklet {// 鼠标位置、点的颜色、大小、间隔、影响半径static get inputProperties() { return ['--mouse-x', '--mouse-y', '--magnet-color', '--magnet-size', '--magnet-gap', '--magnet-radius']; }paint(ctx, size, props) {const mouseX = parseInt(props.get('--mouse-x'));const mouseY = parseInt(props.get('--mouse-y'));const color = props.get('--magnet-color');const lineWidth = parseInt(props.get('--magnet-size'));const gap = parseInt(props.get('--magnet-gap'));const radius = parseInt(props.get('--magnet-radius'));ctx.lineCap = 'round';for (let i = 0; i * gap < size.width; i++) {for (let j = 0; j * gap < size.height; j++) {const posX = i * gap;const posY = j * gap;const distance = Math.sqrt(Math.pow(posX - mouseX, 2) + Math.pow(posY - mouseY, 2));const width = distance < radius ? (1 - distance / radius * distance / radius) * gap * 0.4 : 0;const startPosX = posX - width * 0.5;const endPosX = posX + width * 0.5;const rotate = Math.atan2(mouseY - posY, mouseX - posX);ctx.save();ctx.beginPath();ctx.translate(posX, posY);ctx.rotate(rotate);ctx.translate(-posX, -posY);ctx.moveTo(startPosX, posY);ctx.strokeStyle = color;ctx.lineWidth = lineWidth;ctx.lineCap = 'round';ctx.lineTo(endPosX, posY);ctx.stroke();ctx.closePath();ctx.restore();}}}}registerPaint('magnet-matrix', MagnetMatrixPaintWorklet);}.toString(),')()'], { type: 'application/javascript' })
);export default blobURL;
<template><div class="demo"></div>
</template>
<script>import blobURL from './checkerboard.js';
export default {mounted() {if ('paintWorklet' in CSS) {CSS.paintWorklet.addModule(blobURL);}let div = document.getElementsByTagName('div')[0];div.addEventListener('mouseenter', e => {div.style.setProperty('--mouse-x', e.clientX);div.style.setProperty('--mouse-y', e.clientY);});div.addEventListener('mousemove', e => {div.style.setProperty('--mouse-x', e.clientX);div.style.setProperty('--mouse-y', e.clientY);});div.addEventListener('mouseleave', () => {div.style.setProperty('--mouse-x', -999);div.style.setProperty('--mouse-y', -999);});},
};
</script><style lang="scss" scoped>
div {box-sizing: border-box;padding: 0;margin: 0;
}.demo {width: 100vw;height: 100vh;padding: 80px;--magnet-color: rgb(97, 123, 255);--magnet-size: 2;--magnet-gap: 20;--magnet-radius: 150;background: paint(magnet-matrix);
}
</style>
相关文章:
CSS Houdini
前言 最近看了几篇文章,是关于 CSS Houdini 的。作为一个前端搬砖的还真不知道这玩意,虽然不知道的东西挺多的,但是这玩意有点高大上啊。 Houdini 是一组底层 API,它们公开了 CSS 引擎的各个部分,从而使开发人员能够通…...
C++引用
这里写目录标题引用引用的基本使用引用做函数参数引用作为函数返回值引用的本质常量引用引用与指针的区别&的三种作用引用 引用的基本使用 作用: 给变量起别名 语法: 数据类型 &别名 原名 引用的本质是给变量起别名,因此࿰…...
YOLOv6-目标检测论文解读
文章目录摘要问题算法网络设计BackboneNeckHead标签分配SimOTA(YOLOX提出):TAL(Task alignment learning,TOOD提出)损失函数分类损失框回归损失目标损失行业有用改进自蒸馏图像灰度边界填充量化及部署实验消…...
【factoryio】使用SCL编写 <机械手控制> 程序
使用虚拟工厂软件和博图联合仿真来编写【scl】机械手控制程序 文章目录 目录 文章目录 前言 二、程序编写 1.机械手运行部分 2.启动停止部分 3.急停复位部分 三、完整代码 总结 前言 在前面我们一起写过了许多案例控制的编写,在这一章我们一起来编写一下一个…...
QT学习记录散件
fromLocal8Bit() qt中fromLocal8Bit()函数可以设置编码。 因为QT默认的编码是unicode,不能显示中文的 而windows默认使用(GBK/GB2312/GB18030) 所以使用fromLocal8Bit()函数,可以实现从本地字符集GB到Unicode的转换,从…...
[SSD科普之1] PCIE接口详解及应用模式
PCI-Express(peripheral component interconnect express)是一种高速串行计算机扩展总线标准,它原来的名称为“3GIO”,是由英特尔在2001年提出的,旨在替代旧的PCI,PCI-X和AGP总线标准。一、PCI-E x1/x4/x8/x16插槽模式PCI-E有 x1/…...
Linux设备驱动模型与 sysfs实现分析
RTOS和Linux系统上开发驱动的方式非常的不同,在RTOS系统下,驱动和驱动之间并没有实质性的联系,不同的驱动和BSP之间仅仅通过一层很薄很薄的设备管理框架聚合在一起构成RTOS的设备管理子系统。图形化表示如下: 设备驱动&BSP之间互相独立,互不影响,互不依赖,独立实现,…...
软考高级之制定备考计划
制定备考计划 高项准备时间最好是三个月以上,分为三个阶段来复习。 第一个阶段——熟悉知识点 第二个阶段——刷题 第三个阶段——冲刺复习 具体操作 第一个阶段 这个阶段的复习以教材和视频为主,掌握重要知识点。基础知识要打牢。例如࿱…...
[Pytorch] Linear层输出nan
参考链接: https://discuss.pytorch.org/t/well-formed-input-into-a-simple-linear-layer-output-nan/74720/11 总结原因: numpy需要更新 PS. 查看numpy版本号 打开Anaconda Prompt 进入环境 输入命令conda activate envname 然后输入pip show numpy…...
2023-2-19-What is ‘ template<typename E, E V> ‘?
目录C里面template怎么用inline函数模板类模板函数模板特化C里面template怎么用 template是什么? template其实是C的一种语法糖,本意是去简化程序员的工作. void swap(int *a,int *b){int temp *a;*a *b;*b temp; }比如在写一个交换函数的的时候,参数为两个in…...
华为OD机试题 - 字符串加密(JavaScript)
最近更新的博客 华为OD机试题 - 任务总执行时长(JavaScript) 华为OD机试题 - 开放日活动(JavaScript) 华为OD机试 - 最近的点 | 备考思路,刷题要点,答疑 【新解法】 华为OD机试题 - 最小步骤数(JavaScript) 华为OD机试题 - 任务混部(JavaScript) 华为OD机试题 - N 进…...
美团前端一面手写面试题
实现斐波那契数列 // 递归 function fn (n){if(n0) return 0if(n1) return 1return fn(n-2)fn(n-1) } // 优化 function fibonacci2(n) {const arr [1, 1, 2];const arrLen arr.length;if (n < arrLen) {return arr[n];}for (let i arrLen; i < n; i) {arr.push(arr[…...
2D图像处理:缺陷检测--仿照Halcon的Variation Model
文章目录 基于 C++&Opencv 的检测结果(Robust模式-MAD)一、Variation Model1.1 准备和训练模型方法1.2 比较模板方法1.3 过滤(保留符合缺陷特征的区域)二、参考基于 C++&Opencv 的检测结果(Robust模式-MAD) 一、Variation Model Halcon中的Variation Model主要是将待…...
JavaScript 注释
JavaScript 注释可用于提高代码的可读性。JavaScript 注释JavaScript 不会执行注释。我们可以添加注释来对 JavaScript 进行解释,或者提高代码的可读性。单行注释以 // 开头。本例用单行注释来解释代码:实例// 输出标题:document.getElementB…...
浅谈使用CDN加速的OSS
目录引出OSS对象存储服务CDNCDN加速OSS资源总结引出 之前,我在写项目的时候,因为项目中存在音视频的存储,然后我看圈子里面的人都是使用OSS对象存储来处理,然后我也跟风去使用了,然后在之后,我一个朋友问我…...
华为OD机试题 - 服务依赖(JavaScript)
最近更新的博客 华为OD机试题 - 任务总执行时长(JavaScript) 华为OD机试题 - 开放日活动(JavaScript) 华为OD机试 - 最近的点 | 备考思路,刷题要点,答疑 【新解法】 华为OD机试题 - 最小步骤数(JavaScript) 华为OD机试题 - 任务混部(JavaScript) 华为OD机试题 - N 进…...
整合K8s+SpringCloudK8s+SpringBoot+gRpc
本文使用K8s当做服务注册与发现、配置管理,使用gRpc用做服务间的远程通讯一、先准备K8s我在本地有个K8s单机二、准备service-providerpom<?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.…...
Django框架之模型视图--HttpResponse对象
HttpResponse对象 视图在接收请求并处理后,必须返回HttpResponse对象或子对象。HttpRequest对象由Django创建,HttpResponse对象由开发人员创建。 1 HttpResponse 可以使用django.http.HttpResponse来构造响应对象。 HttpResponse(content响应体, con…...
Linux下的Jenkins安装教程
当前环境 CentOS 7.8Java 11(注意当前jenkins支持的Java版本最低为Java11)FinalShell 3.9(操作环境) 安装Jenkins PS:不建议使用Docker安装Jenkins,因为使用Jenkins的时候一般会调用外部程序,…...
[软件工程导论(第六版)]第5章 总体设计(课后习题详解)
文章目录1. 为每种类型的模块耦合举一个具体例子。2. 为每种类型的模块内聚举一个具体例子。3. 用面向数据流的方法设计下列系统的软件结构。4. 美国某大学共有200名教师,校方与教师工会刚刚签订一项协议。按照协议,所有年工资超过$26000(含$…...
工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...
初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...
CSS设置元素的宽度根据其内容自动调整
width: fit-content 是 CSS 中的一个属性值,用于设置元素的宽度根据其内容自动调整,确保宽度刚好容纳内容而不会超出。 效果对比 默认情况(width: auto): 块级元素(如 <div>)会占满父容器…...
CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...
