【CSS Houdini】Paint API,带你变身前端达芬奇

2023-11-03 19:20

本文主要是介绍【CSS Houdini】Paint API,带你变身前端达芬奇,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

作为 CSS Houdini 所暴露出的API之一,CSS Paint API 从一出现就倍受期待。它通过扩展 CSS 的部分能力,使其提供更强大的表现力。本文将从其定义到应用逐一介绍,来让大家对其有更加深刻的认识。

API 介绍

先简单介绍下什么是 Houdini。

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

Houdini 是一组底层 API,它暴露出一部分 CSS 引擎,给了开发者介入浏览器渲染与布局的能力,从而扩展 CSS 。

就像定义中所说的那样,Paint API 就是针对浏览器渲染过程中 Paint 这一环节而出现的。

需要注意的是,包括接下来要介绍到的 Paint API 在内,现阶段暴露出的 API 大部分仍处于草案或 level 1阶段。

W3C 给出关于 Paint API 的定义为:

CSS Paint API 允许开发者使用 JavaScript 创建对样式与大小变化自适应的 CSS 图像。这种方式创建的图像,可以通过调用 paint() 函数,应用在诸如 background-imageborder-imagemask-image 等属性上。

简单来说,就是 CSS 除了纯色、渐变与外链图片外,现在允许我们自己绘制所需要的图片了。

.box{background-image: paint(custom-image)
}

还是逃不过惯例的看一下 Paint API 的支持性,可以看到与其他 API相比,Paint API 的支持性相对较好

浏览器支持

具体的使用方法可以参考下面的模版:

  1. 创建一个 js 文件,使用 registerPaint() 方法注册一个 PaintWorklet

  2. 调用 addModule() 方法添加此模块

  3. 在 CSS 中使用 paint() 函数调用

下面我们按刚刚所说的流程,简单实战一下。当然不是画蒙娜丽莎,我们一起来实现一个星空的背景,进一步熟悉 Paint API 的使用。

API 应用

创建一个 starry.js ,按上面的格式写好框架。

/* starry.js */
registerPaint('starry', class {paint(ctx, geom, properties) {// code here}
})

这里详细说一下paint()方法,也是绘制自定义图像核心的方法,它有着三个参数。

第一个参数为当前绘制区域的上下文,它的全称为 PaintRenderingContext2D ,熟悉 canvas 的同学看到这个名字也许会觉得眼熟。是的,它是 CanvasRenderingContext2D 的子集。

第二个参数是一个包含当前绘制区域宽高的对象,注意,它是只读的。

第三个参数可以用来获取 CSS 属性。配合 CSS 变量或其他 API,我们可以实现更丰富的功能。我们会在下面的例子中看到关于这个参数更具体的应用。

介绍完参数后,我们就来完善一下 paint() 方法。

这里可以按照在 canvas 中的思路来处理。

  • 先绘制一份渐变的天空

drawSky(ctx, geom) {const { height, width } = geom// 绘制矩形背景ctx.rect(0, 0, width, height)ctx.stroke()// 为矩形背景添加渐变的夜空const skyGradient = ctx.createLinearGradient(0, 0, width, height);skyGradient.addColorStop(0, '#3323CB')skyGradient.addColorStop(1, '#090A55')ctx.fillStyle = skyGradientctx.fill()
}
  • 然后完成一颗星星的绘制

drawStar(ctx) {const starColor = '#FFE900'const x = 10const y = 10const r = 5ctx.translate(x, y)ctx.scale(r, r);ctx.beginPath()// 绘制五角星for (var i = 0; i < 5; i++) {ctx.lineTo(Math.cos((18 + i * 72) / 180 * Math.PI),-Math.sin((18 + i * 72) / 180 * Math.PI));ctx.lineTo(Math.cos((54 + i * 72) / 180 * Math.PI) * 0.5,-Math.sin((54 + i * 72) / 180 * Math.PI) * 0.5);}ctx.closePath();// 填充颜色ctx.fillStyle = starColorctx.fill()}

当然星空不会只有一个星星,我们可以多绘制一些,并让它们随机出现。

drawVariousStars(ctx, geom) {const { width, height } = geomconst Num = 10 // 个数// 随机展示星星for (var i = 0; i < Num; i++) {var r = Math.random() * 5 + 5;var x = Math.random() * width;var y = Math.random() * height * 0.65;var a = Math.random() * 360;this.drawStar(ctx, r, x, y, a);}
}

其他的部分参考框架写就可以了,我们来看一下效果。

到这里,相信大家对 Paint API 的基本能力有所了解,不过我们貌似只用它实现了一些可以用 canvas 或者其他 CSS 能力可以做到的事情,完全没有体现出它的“未来可期”。

还记得文章的第一句话吗:“作为 CSS Houdini 所暴露出的API之一……”。单靠 Paint API 自己, 我们也许会觉得它表现平平,但配合上其他 API,它将展现更强大的能力。

我们接着看上面的例子。

上述代码中有关天空颜色,星星颜色、数量等变量,我们都是用直接定义变量的方式,如果想要渲染两套不一样的天空,恐怕要在写一个 starry2.js。

接下来我们配合另一个 Houdini API —— Properties and Values API 来实现通过配置改变天空的这部分功能。

进阶

同样我们对 Properties and Values API 做一个简单介绍。

CSS Properties and Values API 可以让开发者自定义 CSS 属性,同时设置类型校验、默认值、以及是否继承等属性。

看到“让开发者自定义 CSS 属性”这句话时,相信很多同学第一时间会想到 CSS 变量。没错, 在这方面 Properties and Values APICSS 变量确实很像,不过就像定义中提到的一样,它还可以设置类型校验、默认值等属性,来让浏览器清楚该如何处理该变量。

可以在 JS 或是 CSS 中进行注册。

<script>
window.CSS.registerProperty({name: '--sky-color-start', // 变量名syntax: '<color>', // 类型inherits: false, // 是否继承initialValue: '#fff' // 默认值
})
</script>
<style>
@property --sky-color-start {syntax: '<color>'; // 类型inherits: false; // 是否继承initial-value: #fff; // 默认值
}
</style>

inheritsinitial-value 就像定义中说的那样,表示该变量是否继承与默认值。唯一可能要注意的一点就是 syntax 属性,它代表着变量的类型,同时会对变量进行类型校验。它的值可以是 length, length-percentage, angle, time, resolution, integer, number,  percentage,color, custon-ident,url,image……等任何你可以想到的类型。

现在我们将之前写在代码里的变量按照这种方式进行注册。

<style>
// 天空渐变颜色
@property --sky-color-start {syntax: '<color>';inherits: false;initial-value: #090A55;
}
// 天空渐变颜色
@property --sky-color-end {syntax: '<color>';inherits: false;initial-value: #3323CB;
}
// 星星颜色
@property --star-color {syntax: '<color>';inherits: false;initial-value: #FFE900;
}
// 星星个数
@property --star-num {syntax: '<number>';inherits: false;initial-value: 10;
}
</style>

随后在 starry.js 通过 paint() 方法的第三个参数就可以获取定义好的 CSS 变量

registerPaint('gradient-border', class {// 获取变量,在 paint() 通过 properties 获取static get inputProperties() {return ['--sky-color-start','--sky-color-end','--star-color','--star-num']}paint(ctx, geom, properties){ console.log(properties.get('--sky-color-start').toString()) // 'rgb(9, 10, 85)'console.log(+properties.get('--star-num')) // 10}

由于是通过 Properties and Values API 注册的 CSS 变量,浏览器清楚怎样去处理它的特殊行为,所以我们现在实现一个 hover 改变天空的功能:只需要在 hover 时,改变 CSS 变量的值就可以了,配合 transition,我们可以实现更友好的过渡体验。

.starry {background-image: paint(starry);transition: --sky-color-start 1s ease-in-out;// hover 时修改定义的变量&:hover {--sky-color-start: #f9f8ff;--sky-color-end: #bdefff;--star-color: transparent;}
}
效果图

写在最后

经常关注 CSS 动态的同学们也许会有这样的感受:“这个 CSS 特性很实用,xx需求(样式)终于不用 hack 处理了”,但一看到兼容性心就凉了半截,知识还没能应用就变成了储备,不知道何时才能派上用场。相较于可以通过 Polyfill 处理的 JavaScript,所谓前端三剑客中的 CSS 似乎沉寂了太久。

而 Houdini 正是打破这一局面的存在。今天用了一个小小的例子来介绍 CSS Panit API 的使用,有了它,在以往某些需要设计师提供切图场景时,都可以让我们自信的说一句“这个我自己来就行~”,也让我们在面对不同需求场景时有了更多的解决方案。

不止如此,作为 Houdini 的一员,它们的出现也是给了所有喜欢设计与创造的前端工程师们更多的可能。除了今天提到的 Paint APIProperties and Values API外,还有 Layout APITyped OMFont Metrics APIBox Tree API 等众多能力等待我们去开发,对此感兴趣的同学可以在文末的参考链接中了解更多。

参考链接

Houdini 当前支持性(https://ishoudinireadyyet.com/)

Houdini W3C草案文档(https://drafts.css-houdini.org/)

Houdini 实现案例(https://css-houdini.rocks/)

CSS届的绘图板CSS Paint API简介(https://www.zhangxinxu.com/wordpress/2018/11/css-paint-api-canvas/)

New horizons in CSS: Houdini and the Paint API(https://blog.logrocket.com/new-horizons-in-css-houdini-and-the-paint-api-8b307cf387bb/)

Using the CSS Painting API(https://developer.mozilla.org/en-US/docs/Web/API/CSS_Painting_API/Guide)

这篇关于【CSS Houdini】Paint API,带你变身前端达芬奇的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/340335

相关文章

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

【 html+css 绚丽Loading 】000046 三才归元阵

前言:哈喽,大家好,今天给大家分享html+css 绚丽Loading!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 📚一、效果📚二、信息💡1.简介:💡2.外观描述:💡3.使用方式:💡4.战斗方式:💡5.提升:💡6.传说: 📚三、源代码,上代码,可以直接复制使用🎥效果🗂️目录✍️

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能

Vue3项目开发——新闻发布管理系统(六)

文章目录 八、首页设计开发1、页面设计2、登录访问拦截实现3、用户基本信息显示①封装用户基本信息获取接口②用户基本信息存储③用户基本信息调用④用户基本信息动态渲染 4、退出功能实现①注册点击事件②添加退出功能③数据清理 5、代码下载 八、首页设计开发 登录成功后,系统就进入了首页。接下来,也就进行首页的开发了。 1、页面设计 系统页面主要分为三部分,左侧为系统的菜单栏,右侧

【VUE】跨域问题的概念,以及解决方法。

目录 1.跨域概念 2.解决方法 2.1 配置网络请求代理 2.2 使用@CrossOrigin 注解 2.3 通过配置文件实现跨域 2.4 添加 CorsWebFilter 来解决跨域问题 1.跨域概念 跨域问题是由于浏览器实施了同源策略,该策略要求请求的域名、协议和端口必须与提供资源的服务相同。如果不相同,则需要服务器显式地允许这种跨域请求。一般在springbo

HTML提交表单给python

python 代码 from flask import Flask, request, render_template, redirect, url_forapp = Flask(__name__)@app.route('/')def form():# 渲染表单页面return render_template('./index.html')@app.route('/submit_form',

Java 后端接口入参 - 联合前端VUE 使用AES完成入参出参加密解密

加密效果: 解密后的数据就是正常数据: 后端:使用的是spring-cloud框架,在gateway模块进行操作 <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>30.0-jre</version></dependency> 编写一个AES加密

vue2 组件通信

props + emits props:用于接收父组件传递给子组件的数据。可以定义期望从父组件接收的数据结构和类型。‘子组件不可更改该数据’emits:用于定义组件可以向父组件发出的事件。这允许父组件监听子组件的事件并作出响应。(比如数据更新) props检查属性 属性名类型描述默认值typeFunction指定 prop 应该是什么类型,如 String, Number, Boolean,