自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

現(xiàn)代 CSS 高階技巧,像 Canvas 一樣自由繪圖構(gòu)建樣式!

開(kāi)發(fā) 前端
在今天,是否 CSS 還存在著更進(jìn)一步的功能,能夠?qū)崿F(xiàn)更為強(qiáng)大的效果?沒(méi)錯(cuò),是可以的,這也就引出了今天的主角,CSS Houdini 之 CSS Paint API。

在上一篇文章中 -- 現(xiàn)代 CSS 之高階圖片漸隱消失術(shù)[1],我們借助了 CSS @Property 及 CSS Mask 屬性,成功的實(shí)現(xiàn)了這樣一種圖片漸變消失的效果:

圖片

CodePen Demo -- 基于 @property 和 mask 的文本漸隱消失術(shù)[2]。

但是,這個(gè)效果的缺陷也非常明顯,雖然借助了 SCSS 簡(jiǎn)化了非常多的代碼,但是,如果我們查看編譯后的 CSS 文件,會(huì)發(fā)現(xiàn),在利用 SCSS 只有 80 的代碼的情況下,編譯后的 CSS 文件行數(shù)高達(dá) 2400+ 行,實(shí)在是太夸張了。

圖片

究其原因在于,我們利用原生的 CSS 去控制 400 個(gè)小塊的過(guò)渡動(dòng)畫(huà),控制了 400 個(gè) CSS 變量!代碼量因而變得如此之大。

CSS Houdini 之 CSS Paint API

那么,如何有效的降低代碼量呢?

又或者說(shuō),在今天,是否 CSS 還存在著更進(jìn)一步的功能,能夠?qū)崿F(xiàn)更為強(qiáng)大的效果?

沒(méi)錯(cuò),是可以的,這也就引出了今天的主角,CSS Houdini 之 CSS Paint API。

首先,什么是 CSS Houdini?

Houdini 是一組底層 API,它們公開(kāi)了 CSS 引擎的各個(gè)部分,從而使開(kāi)發(fā)人員能夠通過(guò)加入瀏覽器渲染引擎的樣式和布局過(guò)程來(lái)擴(kuò)展 CSS。Houdini 是一組 API,它們使開(kāi)發(fā)人員可以直接訪問(wèn) CSS 對(duì)象模型[3] (CSSOM),使開(kāi)發(fā)人員可以編寫(xiě)瀏覽器可以解析為 CSS 的代碼,從而創(chuàng)建新的 CSS 功能,而無(wú)需等待它們?cè)跒g覽器中本地實(shí)現(xiàn)。

而 CSS Paint API 則是 W3C 規(guī)范中之一,目前的版本是 CSS Painting API Level 1[4]。它也被稱為 CSS Custom Paint 或者 Houdini's Paint Worklet。

簡(jiǎn)單來(lái)說(shuō)人話,CSS Paint API 的優(yōu)缺點(diǎn)都很明顯。

CSS Paint API 的優(yōu)點(diǎn):

  1. 實(shí)現(xiàn)更為強(qiáng)大的 CSS 功能,甚至是很多 CSS 原本不支持的功能
  2. 將這些自定義的功能,很好的封裝起來(lái),當(dāng)初一個(gè)屬性快速?gòu)?fù)用

當(dāng)然,優(yōu)點(diǎn)看著很美好,缺點(diǎn)也很明顯,CSS Paint API 的缺點(diǎn):

  1. 需要寫(xiě)一定量的 JavaScript 代碼,有一定的上手成本
  2. 現(xiàn)階段兼容的問(wèn)題

小試牛刀 registerPaint

CSS Houdini[5] 的特性就是 Worklet (en-US)[6]。在它的幫助下,你可以通過(guò)引入一行 JavaScript 代碼來(lái)引入配置化的組件,從而創(chuàng)建模塊式的 CSS。不依賴任何前置處理器、后置處理器或者 JavaScript 框架。

廢話不多說(shuō),我們直接來(lái)看一個(gè)最簡(jiǎn)單的例子。

<div style="--color: red"></div>
<div style="--color: blue"></div>
<div style="--color: yellow"></div>

<script>
if (CSS.paintWorklet) {
CSS.paintWorklet.addModule('/CSSHoudini.js');
}
</script>
div {
margin: auto;
width: 100px;
height: 100px;
background: paint(drawBg);
}
// 這個(gè)文件的名字為 CSSHoudini.js
// 對(duì)應(yīng)上面 HTML 代碼中的 CSS.paintWorklet.addModule('/CSSHoudini.js')
registerPaint('drawBg', class {

static get inputProperties() {return ['--color']}

paint(ctx, size, properties) {
const c = properties.get('--color');

ctx.fillStyle = c;
ctx.fillRect(0, 0, size.width, size.height);
}
});

先看看最終的結(jié)果:

圖片

看似有點(diǎn)點(diǎn)復(fù)雜,其實(shí)非常好理解。仔細(xì)看我們的 CSS 代碼,在 background 賦值的過(guò)程中,沒(méi)有直接寫(xiě)具體顏色,而是借助了一個(gè)自定義了 CSS Houdini 函數(shù),實(shí)現(xiàn)了一個(gè)名為 drawBg 的方法。從而實(shí)現(xiàn)的給 Div 上色。

registerPaint 是以 worker 的形式工作,具體有幾個(gè)步驟:

  1. 建立一個(gè) CSSHoudini.js,比如我們想用 CSS Painting API,先在這個(gè) JS 文件中注冊(cè)這個(gè)模塊 registerPaint('drawBg', class),這個(gè) class 是一個(gè)類,下面會(huì)具體講到。
  2. 我們需要在 HTML 中引入 CSS.paintWorklet.addModule('CSSHoudini.js'),當(dāng)然CSSHoudini.js 只是一個(gè)名字,沒(méi)有特定的要求,叫什么都可以。
  3. 這樣,我們就成功注冊(cè)了一個(gè)名為drawBg 的自定義 Houdini 方法,現(xiàn)在,可以用它來(lái)擴(kuò)展 CSS 的功能。
  4. 在 CSS 中使用,就像代碼中示意的那樣background: paint(drawBg)。
  5. 接下來(lái),就是具體的 registerPaint 實(shí)現(xiàn)的 drawBg 的內(nèi)部的代碼。

上面的步驟搞明白后,核心的邏輯,都在我們自定義的 drawBg 這個(gè)方法后面定義的 class 里面。CSS Painting API 非常類似于 Canvas,這里面的核心邏輯就是:

  1. 可以通過(guò)static get inputProperties() {} 拿到各種從 CSS 傳遞進(jìn)來(lái)的 CSS 變量。
  2. 通過(guò)一套類似 Canvas 的 API 完成整個(gè)圖片的繪制工作。

而我們上面 DEMO 做的事情也是如此,獲取到 CSS 傳遞進(jìn)來(lái)的 CSS 變量的值。然后,通過(guò) ctx.fillStyle 和 ctx.fillRect 完成整個(gè)背景色的繪制。

使用 registerPaint 實(shí)現(xiàn)自定義背景圖案

OK,了解了上面最簡(jiǎn)單的 DEMO 之后,接下來(lái)我們嘗試稍微進(jìn)階一點(diǎn)點(diǎn)。利用 registerPaint 實(shí)現(xiàn)一個(gè) circleBgSet 的自定義 CSS 方法,實(shí)現(xiàn)類似于這樣一個(gè)背景圖案:

圖片

?CodePen Demo -- CSS Hudini Example - Background Circle[7]。

首先,我們還是要在 HTML 中,利用 CSS.paintWorklet.addModule('') 注冊(cè)引入我們的 JavaScript 文件。

<div style=""></div>

<script>
if (CSS.paintWorklet) {
CSS.paintWorklet.addModule('/CSSHoudini.js'');
}
</script>

其次,在 CSS 中,我們只需要在調(diào)用 background 屬性的時(shí)候,傳入我們即將要實(shí)現(xiàn)的方法:

div {
width: 100vw;
height: 1000vh;
background: paint(circleBgSet);
--gap: 3;
--color: #f1521f;
--size: 64;
}

可以看到,核心在于 background: paint(circleBgSet),我們將繪制背景的工作,交給接下來(lái)我們要實(shí)現(xiàn)的 circleBgSet 方法。同時(shí),我們定義了 3 個(gè) CSS 變量,它們的作用分別是:

  1. --gap:表示圓點(diǎn)背景的間隙。
  2. -color:表示圓點(diǎn)的顏色。
  3. --size:表示圓點(diǎn)的最大尺寸。

好了,接下來(lái),只需要在 JavaScript 文件中,利用 CSS Painting API 實(shí)現(xiàn) circleBgSet 方法即可。

來(lái)看看完整的 JavaScript 代碼:

// 這個(gè)文件的名字為 CSSHoudini.js
registerPaint(
"circleBgSet",
class {
static get inputProperties() {
return [
"--gap",
"--color",
"--size"
];
}
paint(ctx, size, properties) {
const gap = properties.get("--gap");
const color = properties.get("--color");
const eachSize = properties.get("--size");
const halfSize = eachSize / 2;
const n = size.width / eachSize;
const m = size.height / eachSize;
ctx.fillStyle = color;
for (var i = 0; i < n + 1; i++) {
for (var j = 0; j < m + 1; j++) {
let x = i * eachSize + ( j % 2 === 0 ? halfSize : 0);
let y = j * eachSize / gap;
let radius = i * 0.85;
ctx.beginPath();
ctx.arc(x, y, radius, 0, 2 * Math.PI);
ctx.fill();
}
}
}
}
);

代碼其實(shí)也不多,并且核心的代碼非常好理解。這里,我們?cè)俸?jiǎn)單的解釋下:

  1. static get inputProperties() {},我們?cè)?CSS 代碼中定義了一些 CSS 變量,而需要取到這些變量的話,需要利用到這個(gè)方法。它使我們能夠訪問(wèn)所有 CSS 自定義屬性和它們?cè)O(shè)置的值。
  2. paint(ctx, size, properties) {} 核心繪畫(huà)的方法,其中 ctx 類似于 Canvas 2D 畫(huà)布的 ctx 上下文對(duì)象,size 表示 PaintSize 對(duì)象,可以拿到對(duì)于元素的高寬值,而 properties 則是表示 StylePropertyMapReadOnly 對(duì)象,可以拿到 CSS 變量相關(guān)的信息

圖片

  1. 最終,仔細(xì)看看我們的paint() 方法,核心做的就是拿到 CSS 變量后,基于雙重循環(huán),把我們要的圖案繪制在畫(huà)布上。這里核心就是調(diào)用了下述 4 個(gè)方法,對(duì) Canvas 了解的同學(xué)不難發(fā)現(xiàn),這里的 API 和 Canvas 是一模一樣的。
  • ctx.fillStyle = color
  • ctx.beginPath()
  • ctx.arc(x, y, radius, 0, 2 * Math.PI)
  • ctx.fill()

這里,其實(shí) CSS Houdini 的畫(huà)布 API 是 Canvas API 的是一樣的,具體存在這樣一些映射,我們?cè)诠俜揭?guī)范 CSS Painting API Level 1 - The 2D rendering context[8] 可以查到:

圖片

還記得我們上面?zhèn)魅肓?3 個(gè) CSS 變量嗎?這里我們只需要簡(jiǎn)單改變上面的 3 個(gè) 變量,就可以得到不一樣的圖形。讓我們?cè)囈辉嚕?/p>

div {
width: 100vw;
height: 1000vh;
background: paint(circleBgSet);
// --gap: 3;
// --color: #f1521f;
// --size: 64;
--gap: 6;
--color: #ffcc00;
--size: 75;
}

圖片

又或者:

div {
width: 100vw;
height: 1000vh;
background: paint(circleBgSet);
// --gap: 3;
// --color: #f1521f;
// --size: 64;
--gap: 4;
--color: #0bff00;
--size: 50;
}

圖片

利用 registerPaint 實(shí)現(xiàn)自定義 mask

有了上面的鋪墊,下面我們開(kāi)始實(shí)現(xiàn)我們今天的主題,利用 registerPaint 自定義方法還原實(shí)現(xiàn)這個(gè)效果,簡(jiǎn)化 CSS 代碼量:

圖片

自定義的 paint 方法,不但可以用于 background,你想得到的地方,其實(shí)都可以。

能力越大,責(zé)任越大!在 Houdini 的幫助下你能夠在 CSS 中實(shí)現(xiàn)你自己的布局、柵格、或者區(qū)域特性,但是這么做并不是最佳實(shí)踐。CSS 工作組已經(jīng)做了許多努力來(lái)確保 CSS 中的每一項(xiàng)特性都能正常運(yùn)行,覆蓋各種邊界情況,同時(shí)考慮到了安全、隱私,以及可用性方面的表現(xiàn)。如果你要深入使用 Houdini,確保你也把以上這些事項(xiàng)考慮在內(nèi)!并且先從小處開(kāi)始,再把你的自定義 Houdini 推向一個(gè)富有雄心的項(xiàng)目。

因此,這里,我們利用 CSS Houdini 的 registerPaint 實(shí)現(xiàn)自定義的 mask 屬性繪制。

首先,還是一樣,HTML 中需要引入一下定義了 registerPaint 方法的 JavaScript 文件:

<div></div>

<script>
if (CSS.paintWorklet) {
CSS.paintWorklet.addModule('/CSSHoudini.js');
}
</script>

首先,我們會(huì)實(shí)現(xiàn)一張簡(jiǎn)單的圖片:


div {
width: 300px;
height: 300px;
background: url(https://tvax4.sinaimg.cn/large/6f8a2832gy1g8npte0txnj21jk13a4qr.jpg);
}

效果如下:

圖片

當(dāng)然,我們的目標(biāo)是利用 registerPaint 實(shí)現(xiàn)自定義 mask,那么需要添加一些 CSS 代碼:


div {
width: 300px;
height: 300px;
background: url(https://tvax4.sinaimg.cn/large/6f8a2832gy1g8npte0txnj21jk13a4qr.jpg);
mask: paint(maskSet);
--size-m: 10;
--size-n: 10;
}

這里,我們 mask: paint(maskSet) 表示使用我們自定義的 maskSet 方法,并且,我們引入了兩個(gè) CSS 自定義變量 --size-m 和 --size-n,表示我們即將要用 mask 屬性分隔圖片的行列數(shù)。

接下來(lái),就是具體實(shí)現(xiàn)新的自定義 mask 方法。當(dāng)然,這里我們只是重新實(shí)現(xiàn)一個(gè) mask,而 mask 屬性本身的特性,透明的地方背后的內(nèi)容將會(huì)透明這個(gè)特性是不會(huì)改變的。

JavaScript 代碼:

// 這個(gè)文件的名字為 CSSHoudini.js
registerPaint(
"maskSet",
class {
static get inputProperties() {
return ["--size-n", "--size-m"];
}

paint(ctx, size, properties) {
const n = properties.get("--size-n");
const m = properties.get("--size-m");
const width = size.width / n;
const height = size.height / m;

for (var i = 0; i < n; i++) {
for (var j = 0; j < m; j++) {
ctx.fillStyle = "rgba(0,0,0," + Math.random() + ")";
ctx.fillRect(i * width, j * height, width, height);
}
}
}
}
);

這一段代碼非常好理解,我們做的事情就是拿到兩個(gè) CSS 自定義變量 --size-n 和 --size-m 后,通過(guò)一個(gè)雙循環(huán),依次繪制正方形填滿整個(gè) DIV 區(qū)域,每個(gè)小正方形的顏色為帶隨機(jī)透明度的黑色。

記住,mask 的核心在于,透過(guò)顏色的透明度來(lái)隱藏一個(gè)元素的部分或者全部可見(jiàn)區(qū)域。因此,整個(gè)圖片將變成這樣:

圖片

當(dāng)然,我們這個(gè)自定義 mask 方法也是可以用于 background 的,如果我們把這個(gè)方法作用于 backgorund,你會(huì)更好理解一點(diǎn)。

div {
width: 300px;
height: 300px;
background: paint(maskSet);
// mask: paint(maskSet);
--size-m: 10;
--size-n: 10;
}

實(shí)際的圖片效果是這樣:

圖片

好,回歸正題,我們繼續(xù)。我們最終的效果還是要?jiǎng)赢?huà)效果,Hover 的時(shí)候讓圖片方塊化消失,肯定還是要和 CSS @property 自定義變量發(fā)生關(guān)聯(lián)的,我們簡(jiǎn)單改造下代碼,加入一個(gè) CSS @property 自定義變量。

@property --transition-time {
syntax: '<number>';
inherits: false;
initial-value: 1;
}

div {
width: 300px;
height: 300px;
background: url(https://tvax4.sinaimg.cn/large/6f8a2832gy1g8npte0txnj21jk13a4qr.jpg);
mask: paint(maskSet);
--size-m: 10;
--size-n: 10;
--transition-time: 1;
transition: --transition-time 1s linear;
}

div:hover {
--transition-time: 0;
}

這里,我們引入了 --transition-time 這個(gè)變量。接下來(lái),讓他在 maskSet 函數(shù)中,發(fā)揮作用:

registerPaint(
"maskSet",
class {
static get inputProperties() {
return ["--size-n", "--size-m", "--transition-time"];
}

paint(ctx, size, properties) {
const n = properties.get("--size-n");
const m = properties.get("--size-m");
const t = properties.get("--transition-time");
const width = size.width / n;
const height = size.height / m;

for (var i = 0; i < n; i++) {
for (var j = 0; j < m; j++) {
ctx.fillStyle = "rgba(0,0,0," + (t * (Math.random() + 1)) + ")";
ctx.fillRect(i * width, j * height, width, height);
}
}
}
}
);

這里,與上面唯一的變化在于這一行代碼:ctx.fillStyle = "rgba(0,0,0," + (t * (Math.random() + 1)) + ")"。

對(duì)于每一個(gè)小格子的 mask,我們讓他的顏色值的透明度設(shè)置為 (t * (Math.random() + 1)):

  1. 其中 t 就是--transition-time 這個(gè)變量,記住,在 hover 的過(guò)程中,它的值會(huì)逐漸從 1 衰減至 0
  2. (Math.random() + 1) 表示先生成一個(gè) 0 ~ 1 的隨機(jī)數(shù),再讓這個(gè)隨機(jī)數(shù)加 1,加 1 的目的是讓整個(gè)值必然大于 1,處于 1 ~ 2 的范圍
  3. 由于一開(kāi)始--transition-time 的值一開(kāi)始是 1,所以乘以 (Math.random() + 1) 的值也必然大于 1,而最終在過(guò)渡過(guò)程中 --transition-time 會(huì)逐漸變?yōu)?0, 整個(gè)表達(dá)式的值也最終會(huì)歸于 0
  4. 由于上述 (3)的值控制的是每一個(gè) mask 小格子的透明度,也就是說(shuō)每個(gè)格子的透明度都會(huì)從一個(gè)介于 1 ~ 2 的值逐漸變成 0,借助這個(gè)過(guò)程,我們完成了整個(gè)漸隱的動(dòng)畫(huà)

看看最終的效果:

圖片

?CodePen Demo -- CSS Hudini Example[9]。

是的,細(xì)心的同學(xué)肯定會(huì)發(fā)現(xiàn),文章一開(kāi)頭給的 DEMO 是切分了 400 份 mask 的,而我們上面實(shí)現(xiàn)的效果,只用了 100 個(gè) mask。

這個(gè)非常好解決,我們不是傳入了 --size-n? 和 --size-m 兩個(gè)變量么?只需要修改這兩個(gè)值,就可以實(shí)現(xiàn)任意格子的 Hover 漸隱效果啦。還是上面的代碼,簡(jiǎn)單修改 CSS 變量的值:

div:nth-child(1) {
--size-m: 4;
--size-n: 4;
}
div:nth-child(2) {
--size-m: 6;
--size-n: 6;
}
div:nth-child(3) {
--size-m: 10;
--size-n: 10;
}
div:nth-child(4) {
--size-m: 15;
--size-n: 15;
}

結(jié)果如下:

圖片

?CodePen Demo -- CSS Hudini Example[10]。

到這里,還有一個(gè)小問(wèn)題,可以看到,在消失的過(guò)程中,整個(gè)效果非常的閃爍!每個(gè)格子其實(shí)閃爍了很多次。

這是由于在過(guò)渡的過(guò)程中,ctx.fillStyle = "rgba(0,0,0," + (t * (Math.random() + 1)) + ")"? 內(nèi)的 Math.random() 每一幀都會(huì)重新被調(diào)用并且生成全新的隨機(jī)值,因此整個(gè)動(dòng)畫(huà)過(guò)程一直在瘋狂閃爍。

如何解決這個(gè)問(wèn)題?在這篇文章中,我找到了一種利用偽隨機(jī),生成穩(wěn)定隨機(jī)函數(shù)的方法:Exploring the CSS Paint API: Image Fragmentation Effect[11]。

啥意思呢?就是我們希望每次生成的隨機(jī)數(shù)都是都是一致的。其 JavaScript 代碼如下:

const mask = 0xffffffff;
const seed = 30; /* update this to change the generated sequence */
let m_w = (123456789 + seed) & mask;
let m_z = (987654321 - seed) & mask;

let random = function() {
m_z = (36969 * (m_z & 65535) + (m_z >>> 16)) & mask;
m_w = (18000 * (m_w & 65535) + (m_w >>> 16)) & mask;
var result = ((m_z << 16) + (m_w & 65535)) >>> 0;
result /= 4294967296;
return result;
}

我們利用上述實(shí)現(xiàn)的隨機(jī)函數(shù) random() 替換掉我們代碼原本的 Math.random(),并且,mask 小格子的 ctx.fillStyle 函數(shù),也稍加變化,避免每一個(gè) mask 矩形小格子的漸隱淡出效果同時(shí)發(fā)生。

修改后的完整 JavaScript 代碼如下:

registerPaint(
"maskSet",
class {
static get inputProperties() {
return ["--size-n", "--size-m", "--transition-time"];
}

paint(ctx, size, properties) {
const n = properties.get("--size-n");
const m = properties.get("--size-m");
const t = properties.get("--transition-time");
const width = size.width / n;
const height = size.height / m;
const l = 10;

const mask = 0xffffffff;
const seed = 100; /* update this to change the generated sequence */
let m_w = (123456789 + seed) & mask;
let m_z = (987654321 - seed) & mask;

let random = function () {
m_z = (36969 * (m_z & 65535) + (m_z >>> 16)) & mask;
m_w = (18000 * (m_w & 65535) + (m_w >>> 16)) & mask;
var result = ((m_z << 16) + (m_w & 65535)) >>> 0;
result /= 4294967296;
return result;
};

for (var i = 0; i < n; i++) {
for (var j = 0; j < m; j++) {
ctx.fillStyle = 'rgba(0,0,0,'+((random()*(l-1) + 1) - (1-t)*l)+')';
ctx.fillRect(i * width, j * height, width, height);
}
}
}
}
);

還是上述的 DEMO,讓我們?cè)賮?lái)看看效果,分別設(shè)置了不同數(shù)量的 mask 漸隱消失:

圖片

CodePen Demo -- CSS Hudini Example & Custom Random[12]。

Wow!修正過(guò)后的效果不再閃爍,并且消失動(dòng)畫(huà)也并非同時(shí)進(jìn)行。在 Exploring the CSS Paint API: Image Fragmentation Effect[13] 這篇文章中,還介紹了一些其他利用 registerPaint 實(shí)現(xiàn)的有趣的 mask 漸隱效果,感興趣可以深入再看看。

這樣,我們就將原本 2400 行的 CSS 代碼,通過(guò) CSS Painting API 的 registerPaint,壓縮到了 50 行以內(nèi)的 JavaScript 代碼。

當(dāng)然,CSS Houdini 的本事遠(yuǎn)不止于此,本文一直在圍繞 background 描繪相關(guān)的內(nèi)容進(jìn)行闡述(mask 的語(yǔ)法也是背景 background 的一種)。在后續(xù)的文章我將繼續(xù)介紹在其他屬性上的應(yīng)用。

兼容性如何?

那么,CSS Painting API 的兼容性到底如何呢?

CanIUse - registerPaint[14] 數(shù)據(jù)如下(截止至 2022-11-23):

圖片

Chrome 和 Edge 基于 Chromium[15] 內(nèi)核的瀏覽器很早就已經(jīng)支持,而主流瀏覽器中,F(xiàn)irefox 和 Safari 目前還不支持。

CSS Houdini 雖然強(qiáng)大,目前看來(lái)要想大規(guī)模上生產(chǎn)環(huán)境,仍需一段時(shí)間的等待。讓我們給時(shí)間一點(diǎn)時(shí)間!

最后

好了,本文到此結(jié)束,希望本文對(duì)你有所幫助 :)

參考資料

[1]現(xiàn)代 CSS 之高階圖片漸隱消失術(shù): ?https://github.com/chokcoco/cococss/issues/23?。?

[2]CodePen Demo -- 基于 @property 和 mask 的文本漸隱消失術(shù): ?https://codepen.io/Chokcoco/pen/qBKPgZY?。?

[3]CSS 對(duì)象模型: ?https://developer.mozilla.org/zh-CN/docs/Web/API/CSS_Object_Model?。?

[4]CSS Painting API Level 1: ?https://drafts.css-houdini.org/css-paint-api/#paintworkletglobalscope?。?

[5]CSS Houdini: ?https://developer.mozilla.org/zh-CN/docs/Web/Guide/Houdini?。?

[6]Worklet (en-US): ?https://developer.mozilla.org/en-US/docs/Web/API/Worklet?。?

[7]CodePen Demo -- CSS Hudini Example - Background Circle: ?https://codepen.io/Chokcoco/pen/abKExxN?。?

[8]CSS Painting API Level 1 - The 2D rendering context: ?https://drafts.css-houdini.org/css-paint-api/#paintworkletglobalscope?。?

[9]CodePen Demo -- CSS Hudini Example: https://codepen.io/Chokcoco/pen/KKeQWJb。?

[10]CodePen Demo -- CSS Hudini Example: ?https://codepen.io/Chokcoco/pen/oNyEpLN?。?

[11]Exploring the CSS Paint API: Image Fragmentation Effect: ?https://dev.to/this-is-learning/exploring-the-css-paint-api-image-fragmentation-effect-3ekl?。?

[12]CodePen Demo -- CSS Hudini Example & Custom Random: ?https://codepen.io/Chokcoco/pen/eYKVQGG?。?

[13]Exploring the CSS Paint API: Image Fragmentation Effect: ?https://dev.to/this-is-learning/exploring-the-css-paint-api-image-fragmentation-effect-3ekl?。?

[14]CanIUse - registerPaint: ?https://caniuse.com/?search=registerPaint?。?

[15]Chromium: ?https://www.google.com.hk/search?newwindow=1&rlz=1C5GCEM_enCN988CN988&q=Chromium&spell=1&sa=X&ved=2ahUKEwi3he2ensL7AhVaSmwGHdnzBxgQkeECKAB6BAgoEAE?

責(zé)任編輯:姜華 來(lái)源: iCSS前端趣聞
相關(guān)推薦

2023-11-01 08:36:07

CSSTailwind

2021-09-07 10:29:11

JavaScript模塊CSS

2022-12-22 08:34:22

CSS不規(guī)則圖形

2021-08-12 06:08:15

CSS 技巧組件狀態(tài)

2023-04-05 14:19:07

FlinkRedisNoSQL

2013-12-17 09:02:03

Python調(diào)試

2022-12-21 15:56:23

代碼文檔工具

2023-05-23 13:59:41

RustPython程序

2013-12-31 09:19:23

Python調(diào)試

2015-03-16 12:50:44

2013-08-22 10:17:51

Google大數(shù)據(jù)業(yè)務(wù)價(jià)值

2021-05-20 08:37:32

multiprocesPython線程

2011-01-18 10:45:16

喬布斯

2012-06-08 13:47:32

Wndows 8Vista

2015-02-05 13:27:02

移動(dòng)開(kāi)發(fā)模塊SDK

2022-08-09 09:38:29

JavaScript函數(shù)

2024-08-29 08:07:59

GoAPI開(kāi)發(fā)

2012-03-21 10:15:48

RIM越獄

2017-05-22 10:33:14

PythonJuliaCython

2021-12-14 19:40:07

Node路由Vue
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)