.說明:
1.1 推薦指數:★★★★
1.2 環境:谷歌瀏覽器、微軟vscode編輯器
1.3 熟悉sin和cos的函數與圓(畫圓弧的關系)深入理解
比較真實的雷達界面掃描圖
2.本次的模擬效果圖:
3.css和js文件的引入:
3.1 同一個文件夾或者目錄下引入:./xxx.js或者./xxx.css
3.2 大型的html文件或者一般在html文件的同一個目錄下,建css文件夾和js文件夾,放入相應文件夾下,那么導入就是:css/xxx.css和js/xxxx.js
3.3 外部引入法:找到網址:比如:網址在代碼注釋里query-3.4.1.min.js,引入即可。
但是如果沒有網絡,那么html文件就不可用了,怎么辦呢?有辦法。
用瀏覽器打開,復制:網址在代碼注釋里jquery-3.4.1.min.js,打開。
全選復制(ctrl+a),在本地文件夾新建一個js文件:jquery-3.4.1.min.js,將復制的內容,黏貼進入,保存即可。向上面的js文件和css文件一樣,作為本地js文件引入。
4.本次html文件代碼:index.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Canvas帶坐標雷達掃描特效</title>
<!--在線引入地址:https://code.jquery.com/jquery-3.4.1.min.js-->
<!--script-- src="./jquery.min.js"></!--script-->
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<!--將style作為單獨css文件,引入,否認就是style和/style的標簽內-->
<!--采用下面格式:link法-->
<link type="text/css" href="./style.css" rel="stylesheet" />
</head>
<body>
<canvas id="myCanvas"></canvas>
<div class="info">
<!--顯示文字段落-->
<h1>Warning!!Enemy is coming!!</h1>
<!--初始化cs-xo,之后就是message彈出動態數據-->
<p class="message">cs-xo</p>
</div>
<!--將radar.js作為單獨js文件,引入,否認就是script和/script的標簽內-->
<script src="./radar.js"></script>
</body>
</html>
注意:外部引入和本地引入基本沒什么區別,如果css和js=JavaScript寫在html內,可能有不同,上面注釋里有提到。
5.jquery-3.4.1.min.js代碼不寫了,可以自己去下載,免費的,或者上面的有講解如何操作,此處略。
6.新建一個radar.js文件,代碼如下:
var c=$("#myCanvas")[0];
var ctx=c.getContext("2d");
/*雷達界面顏色=草地綠色*/
var color_gold="124,252,0"
var ww,wh;
var center={x: 0,y: 0};
// 定義函數
function getWindowSize(){
ww=$(window).outerWidth();
wh=$(window).outerHeight();
c.width=ww;
c.height=wh;
// 中心坐標是窗口的一半
center={x: ww/2,y: wh/2};
ctx.restore();
ctx.translate(center.x,center.y);
}
// 啟動函數
getWindowSize();
$(window).resize(getWindowSize);
// 10=敵機數量,隨機出現
var enemies=Array(10).fill({}).map(
function(obj){
return {
r: Math.random()*200,
deg: Math.random()*360,
opacity: 0
}
}
);
setInterval(draw,10);
var time=0;
var deg_to_pi=Math.PI/180;
// 畫圓的函數,三角函數sin和cos畫圓法
function Point(r,deg){
return {
x: r*Math.cos(deg_to_pi*deg),
y: r*Math.sin(deg_to_pi*deg),
};
}
/*定義顏色函數*/
function Color(op){
return "rgba("+color_gold+","+op+")";
}
function draw(){
time+=1;
/*畫長方形的背景顏色填充 "#111"=黑色;*/
ctx.fillStyle="#111";
ctx.beginPath();
/*畫長方形*/
ctx.rect(-2000,-2000,4000,4000);
ctx.fill();
/*十字垂直水平坐標線,0.1~1代表粗細*/
ctx.strokeStyle="rgba(255,125,64,0.5)";
// ctx.strokeStyle="255,125,64";// 默認粗細值為1
ctx.moveTo(-ww/2,0);
ctx.lineTo(ww/2,0);
ctx.moveTo(0,-wh/2);
ctx.lineTo(0,wh/2);
ctx.stroke();
// 雷達掃面綠色和半徑大小
ctx.strokeStyle=Color(1);
var r=300;
var deg=time;
var newpoint=Point(r,deg);
var line_deg=(time/2) % 360;
// 雷達動態轉動的掃描扇形的弧度為100,最大360
var line_deg_len=100;
for(var i=0;i<line_deg_len;i++){
var deg1=(line_deg-i-1) ;
var deg2=(line_deg-i) ;
var point1=Point(r,deg1);
var point2=Point(r,deg2);
// 代表隨著雷達掃描扇形的移動,顏色逐漸變淡
var opacity=1-(i/line_deg_len)-0.3;
if (i==0) opacity=1;
ctx.beginPath();
// 雷達扇形綠色動態漸變淡色
ctx.fillStyle=Color(opacity);
ctx.moveTo(0,0);
ctx.lineTo(point1.x,point1.y);
ctx.lineTo(point2.x,point2.y);
ctx.fill();
}
enemies.forEach(function(obj){
// 敵機出現的原點
ctx.fillStyle=Color(obj.opacity);
var obj_point=Point(obj.r,obj.deg);
ctx.beginPath();
ctx.arc(
obj_point.x,obj_point.y,
// 綠色敵機出現的小圓點4是半徑
4,0,2*Math.PI
);
ctx.fill();
ctx.strokeStyle=Color(obj.opacity);
/*如果這樣直接設置,ctx.strokeStyle='#FF4500,那么敵機就是一直出現在屏幕';*/
var x_size=6;
/* 雷達顯示敵機目標大小設置*/
ctx.lineWidth=4;
ctx.beginPath();
ctx.moveTo(obj_point.x-x_size,obj_point.y+x_size);
ctx.lineTo(obj_point.x+x_size,obj_point.y-x_size);
ctx.moveTo(obj_point.x+x_size,obj_point.y+x_size);
ctx.lineTo(obj_point.x-x_size,obj_point.y-x_size);
ctx.stroke();
if (Math.abs(obj.deg - line_deg)<=1){
obj.opacity=1;
// 顯示左上角偵查到的地理坐標
$(".message").text("Detected: "+ obj.r.toFixed(3) + " at " +obj.deg.toFixed(3));
}
obj.opacity*=0.99;
// 顯示敵機出現的漣漪圈的顏色
ctx.strokeStyle=Color(obj.opacity);
/*目標敵機顯示后的圓圈漣漪粗細設置*/
ctx.lineWidth=1;
ctx.beginPath();
ctx.arc(
obj_point.x,obj_point.y,
10*(1/(obj.opacity+0.0001)),0,2*Math.PI
);
ctx.stroke();
});
// 雷達虛點固定圓盤的顏色,半徑等設置
ctx.strokeStyle='yellow';
var split=120;
var feature=15; // 15個小格
var start_r=230; // 半徑
var len=5;
for(var i=0;i<split;i++){
ctx.beginPath();
var deg=(i/120) * 360;
if (i%feature==0){
len=10;
ctx.lineWidth=5;
}else{
len=5;
ctx.lineWidth=1;
}
var point1=Point(start_r,deg);
var point2=Point(start_r+len,deg);
ctx.moveTo(point1.x,point1.y);
ctx.lineTo(point2.x,point2.y);
ctx.stroke();
}
/*畫圈函數定義,下面三個畫圓函數的定義*/
function CondCircle(r,lineWidth,func_cond){
ctx.lineWidth=lineWidth;
/* 顏色定義*/
/*注意顏色定義:有引號的和沒有引號的區別,就是前面有沒有顏色圖標*/
ctx.strokeStyle='#00C78C';
ctx.beginPath();
for(var i=0;i<=360;i++){
var point=Point(r,i);
if (func_cond(i)){
ctx.lineTo(point.x,point.y);
}else{
ctx.moveTo(point.x,point.y);
}
}
ctx.stroke();
}
// 雷達外圍的移動半弧形,300為半徑,2代表粗細
CondCircle(300,2,function(deg){
return ((deg+time/10)%180)<90;
});
// 雷達中間綠色的移動半弧形,160為半徑,2代表粗細
CondCircle(160,2,function(deg){
return ((deg+time/5)%180)<90;
});
// 雷達內的小圓圈,綠色虛線圈,1代表粗細
CondCircle(100,1,function(deg){
// 如果這里沒有,那么顏色就是三條線函數里統一的顏色,也可以單獨設立
ctx.strokeStyle='pink';
return (deg%3)<1;
});
}
7.新建一個style.css文件,代碼如下:
html, body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
/*隱藏瀏覽器的條形伸縮*/
overflow: hidden;
}
/*定義畫布*/
canvas {
-webkit-transform: scaleY(-1);
transform: scaleY(-1);
}
/*顯示警告信息位置設置*/
.info {
position: absolute;
left: 10px;
top: 10px;
}
h1 {
/*顯示警告信息文字顏色設置*/
color:red;
letter-spacing: 0.5px;
margin: 0;
font-size:smaller;
}
.message {
/*顯示雷達預警敵機的動態位置的文字顏色設置*/
margin: 0;
color:#00FFFF;
font-size: x-large;
}
8.通過簡單的例子,熟悉html、css和js的關系和布局等基本知識,熟練掌握基本操作。
計算機科學中,路徑是指向文件系統中某個位置的字符串。路徑可以是絕對的也可以是相對的。這篇文章將詳細解釋絕對路徑和相對路徑的區別,并通過例子來展示它們的使用。
絕對路徑是從文件系統的根目錄(在Windows系統中是驅動器的根,如C:\,在UNIX系統中是/)開始的完整路徑。它包含了從根目錄到目標文件或文件夾的所有目錄名,并以文件或文件夾名結束。
假設我們有一個位于Windows系統D盤的圖片文件,其路徑可能是:
D:\Photos\Holiday\beach.jpg
在UNIX系統中,如果有一個配置文件位于根目錄下的etc文件夾中,其路徑可能是:
/etc/nginx/nginx.conf
無論當前位置在哪里,上述路徑都準確指向了特定的文件。
相對路徑是相對于當前工作目錄的路徑。它不是從根目錄開始,而是從當前目錄開始描述如何到達目標文件或文件夾。
假設當前工作目錄是D:\Photos,要引用Holiday文件夾中的beach.jpg圖片,相對路徑將是:
Holiday\beach.jpg
如果需要引用同一級別目錄下的另一個文件夾中的文件,例如當前工作目錄是D:\Photos\Holiday,要引用Work文件夾中的report.docx文件,相對路徑將使用..來表示上一級目錄:
..\Work\report.docx
在UNIX系統中,如果當前工作目錄是/etc/nginx,要引用同一級別的apache2目錄下的apache2.conf文件,相對路徑將是:
../apache2/apache2.conf
在相對路徑中,有兩個特殊符號經常使用:
使用這些符號,可以在文件系統中向上或向下導航。
在創建網頁時,鏈接到CSS文件、JavaScript文件、圖片或其他網頁通常需要使用路徑。使用絕對路徑或相對路徑取決于資源的位置和你的特定需求。
假設網站的根目錄結構如下:
/ (根目錄)
|-- index.html
|-- about.html
|-- css
| |-- styles.css
|-- images
| |-- logo.png
|-- js
|-- scripts.js
如果在index.html中引用styles.css,相對路徑將是:
<link rel="stylesheet" type="text/css" href="css/styles.css">
如果在index.html中引用logo.png,相對路徑將是:
<img src="images/logo.png" alt="Logo">
如果網站的URL是http://www.example.com,那么引用logo.png的絕對路徑將是:
<img src="http://www.example.com/images/logo.png" alt="Logo">
絕對路徑和相對路徑都是定位文件系統中文件和文件夾的有效方式。絕對路徑提供了明確的位置,不依賴于當前工作目錄,而相對路徑則更加靈活,可以簡化文件的鏈接,尤其是在網頁設計和軟件開發中。理解這兩種路徑的差異和應用場景,對于任何與文件系統交互的活動都是至關重要的。
CSS in JS是一種解決css問題想法的集合,而不是一個指定的庫。從CSS in JS的字面意思可以看出,它是將css樣式寫在JavaScript文件中,而不需要獨立出.css、.less之類的文件。將css放在js中使我們更方便的使用js的變量、模塊化、tree-shaking。還解決了css中的一些問題,譬如:更方便解決基于狀態的樣式,更容易追溯依賴關系,生成唯一的選擇器來鎖定作用域。盡管CSS in JS不是一個很新的技術,但國內的普及程度并不高。由于Vue和Angular都有屬于他們自己的一套定義樣式的方案,React本身也沒有管用戶怎樣定義組件的樣式[1],所以CSS in JS在React社區的熱度比較高。
目前為止實現CSS in JS的第三方庫有很多:(http://michelebertoli.github.io/css-in-js/)。像JSS[2]、styled-components[3]等。在這里我們就不展開贅述了(相關鏈接已放在下方),這篇文章的重點是JS in CSS。
在上面我們提到CSS in JS就是把CSS寫在JavaScript中,那么JS in CSS我們可以推斷出就是可以在CSS中使用JavaScript腳本,如下所示。可以在CSS中編寫Paint API的功能。還可以訪問:ctx,geom。甚至我們還可以編寫自己的css自定義屬性等。這些功能的實現都基于CSS Houdini[4]。
.el {
--color: cyan;
--multiplier: 0.24;
--pad: 30;
--slant: 20;
--background-canvas: (ctx, geom) => {
let multiplier = var(--multiplier);
let c = `var(--color)`;
let pad = var(--pad);
let slant = var(--slant);
ctx.moveTo(0, 0);
ctx.lineTo(pad + (geom.width - slant - pad) * multiplier, 0);
ctx.lineTo(pad + (geom.width - slant - pad) * multiplier + slant, geom.height);
ctx.lineTo(0, geom.height);
ctx.fillStyle = c;
ctx.fill();
};
background: paint(background-canvas);
transition: --multiplier .4s;
}
.el:hover {
--multiplier: 1;
}
在如今的Web開發中,JavaScript幾乎占據了項目代碼的大部分。我們可以在項目開發中使用ES 2020、ES2021、甚至提案中的新特性(如:Decorator[5]),即使瀏覽器尚未支持,也可以編寫Polyfill或使用Babel之類的工具進行轉譯,讓我們可以將最新的特性應用到生產環境中(如下圖所示)。
JavaScript標準制定流程.png
而CSS就不同了,除了制定CSS標準規范所需的時間外,各家瀏覽器的版本、實戰進度差異更是曠日持久(如下圖所示),最多利用PostCSS、Sass等工具來幫我們轉譯出瀏覽器能接受的CSS。開發者們能操作的就是通過JS去控制DOM與CSSOM來影響頁面的變化,但是對于接下來的Layout、Paint與Composite就幾乎沒有控制權了。為了解決上述問題,為了讓CSS的魔力不在受到瀏覽器的限制,Houdini就此誕生。
CSS 標準制定流程.png
我們上文中提到JavaScript中進入提案中的特性我們可以編寫Polyfill,只需要很短的時間就可以講新特性投入到生產環境中。這時,腦海中閃現出的第一個想法就是CSS Polyfill,只要CSS的Polyfill 足夠強大,CSS或許也能有JavaScript一樣的發展速度,令人可悲的是編寫CSS Polyfill異常的困難,并且大多數情況下無法在不破壞性能的情況下進行。這是因為JavaScript是一門動態腳本語言[6]。它帶來了極強的擴展性,正是因為這樣,我們可以很輕松使用JavaScript做出JavaScript的Polyfill。但是CSS不是動態的,在某些場景下,我們可以在編譯時將一種形式的CSS的轉換成另一種(如PostCSS[7])。如果你的Polyfill依賴于DOM結構或者某一個元素的布局、定位等,那么我們的Polyfill就無法編譯時執行,而需要在瀏覽器中運行了。不幸的是,在瀏覽器中實現這種方案非常不容易。
頁面渲染流程.png
如上圖所示,是從瀏覽器獲取到HTML到渲染在屏幕上的全過程,我們可以看到只有帶顏色(粉色、藍色)的部分是JavaScript可以控制的環節。首先我們根本無法控制瀏覽器解析HTML與CSS并將其轉化為DOM與CSSOM的過程,以及Cascade,Layout,Paint,Composite我們也無能為力。整個過程中我們唯一完全可控制的就是DOM,另外CSSOM部分可控。
CSS Houdini草案中提到,這種程度的暴露是不確定的、兼容性不穩定的以及缺乏對關鍵特性的支持的。比如,在瀏覽器中的 CSSOM 是不會告訴我們它是如何處理跨域的樣式表,而且對于瀏覽器無法解析的 CSS 語句它的處理方式就是不解析了,也就是說——如果我們要用 CSS polyfill讓瀏覽器去支持它尚且不支持的屬性,那就不能在 CSSOM 這個環節做,我們只能遍歷一遍DOM,找到 <style> 或 <link rel="stylesheet"> 標簽,獲取其中的 CSS 樣式、解析、重寫,最后再加回 DOM 樹中。令人尷尬的是,這樣DOM樹全部刷新了,會導致頁面的重新渲染(如下如所示)。
即便如此,有的人可能會說:“除了這種方法,我們也別無選擇,更何況對網站的性能也不會造成很大的影響”。那么對于部分網站是這樣的。但如果我們的Polyfill是需要對可交互的頁面呢?例如scroll,resize,mousemove,keyup等等,這些事件隨時會被觸發,那么意味著隨時都會導致頁面的重新渲染,交互不會像原本那樣絲滑,甚至導致頁面崩潰,對用戶的體驗也極其不好。
綜上所述,如果我們想讓瀏覽器解析它不認識的樣式(低版本瀏覽器使用grid布局),然而渲染流程我們無法介入,我們也只能通過手動更新DOM的方式,這樣會帶來很多問題,Houdini的出現正是致力于解決他們。
Houdini是一組底層API,它公開了CSS引擎的各個部分,如下圖所示展示了每個環節對應的新API(灰色部分各大瀏覽器還未實現),從而使開發人員能夠通過加入瀏覽器渲染引擎的樣式和布局過程來擴展CSS。Houdini是一群來自Mozilla,Apple,Opera,Microsoft,HP,Intel和Google的工程師組成的工作小組設計而成的。它們使開發者可以直接訪問CSS對象模型(CSSOM),使開發人員可以編寫瀏覽器可以解析為CSS的代碼,從而創建新的CSS功能,而無需等待它們在瀏覽器中本地實現。
CSS Houdini-API
盡管當前已經有了CSS變量,可以讓開發者控制屬性值,但是無法約束類型或者更嚴格的定義,CSS Houdini新的API,我們可以擴展css的變量,我們可以定義CSS變量的類型,初始值,繼承。它是css變量更強大靈活。
CSS變量現狀:
.dom {
--my-color: green;
--my-color: url('not-a-color'); // 它并不知道當前的變量類型
color: var(--my-color);
}
Houdini提供了兩種自定義屬性的注冊方式,分別是在js和css中。
CSS.registerProperty({
name: '--my-prop', // String 自定義屬性名
syntax: '<color>', // String 如何去解析當前的屬性,即屬性類型,默認 *
inherits: false, // Boolean 如果是true,子節點將會繼承
initialValue: '#c0ffee', // String 屬性點初始值
});
我們還可以在css中注冊,也可以達到上面的效果
@property --my-prop {
syntax: '<color>';
inherits: false;
initial-value: #c0ffee;
}
這個API中最令人振奮人心的功能是自定義屬性上添加動畫,像這樣:transition: --multiplier 0.4s;,這個功能我們在前面介紹什么是js in css那個demo[8]用使用過。我們還可以使用+使syntax屬性支持一個或多個類型,也可以使用|來分割。更多syntax屬性值:
屬性值描述<length>長度值<number>數字<percentage>百分比<length-percentage>長度或百分比,calc將長度和百分比組成的表達式<color>顏色<image>圖像<url>網址<integer>整數<angle>角度<time>時間<resolution>分辨率<transform-list>轉換函數<custom-ident>ident
Worklets是渲染引擎的擴展,從概念上來講它類似于Web Workers[9],但有幾個重要的區別:
Worklet是一個JavaScript模塊,通過調用worklet的addModule方法(它是個Promise)來添加。比如registerLayout,registerPaint, registerAnimator 我們都需要放在Worklet中
//加載單個
await demoWorklet.addModule('path/to/script.js');
// 一次性加載多個worklet
Promise.all([
demoWorklet1.addModule('script1.js'),
demoWorklet2.addModule('script2.js'),
]).then(results => {});
registerDemoWorklet('name', class {
// 每個Worklet可以定義要使用的不同函數
// 他們將由渲染引擎在需要時調用
process(arg) {
return !arg;
}
});
Worklets的生命周期
Worklets lifecycle
Typed OM是對現有的CSSOM的擴展,并實現 Parsing API 和 Properties & Values API相關的特性。它將css值轉化為有意義類型的JavaScript的對象,而不是像現在的字符串。如果我們嘗試將字符串類型的值轉化為有意義的類型并返回可能會有很大的性能開銷,因此這個API可以讓我們更高效的使用CSS的值。
現在讀取CSS值增加了新的基類CSSStyleValue,他有許多的子類可以更加精準的描述css值的類型:
子類描述CSSKeywordValueCSS關鍵字和其他標識符(如inherit或grid)CSSPositionValue位置信息 (x,y)CSSImageValue表示圖像的值屬性的對象CSSUnitValue表示為具有單個單位的單個值(例如50px),也可以表示為沒有單位的單個值或百分比CSSMathValue比較復雜的數值,比如有calc,min和max。這包括子類 CSSMathSum, CSSMathProduct, CSSMathMin,CSSMathMax, CSSMathNegate 和 CSSMathInvertCSSTransformValue由CSS transforms組成的CSSTransformComponent列表,其中包括CSSTranslate, CSSRotate, CSSScale, CSSSkew, CSSSkewX, CSSSkewY, CSSPerspective 和 CSSMatrixComponent
使用Typed OM主要有兩種方法:
使用attributeStyleMap設置并獲取
myElement.attributeStyleMap.set('font-size', CSS.em(2));
myElement.attributeStyleMap.get('font-size'); // CSSUnitValue { value: 2, unit: 'em' }
myElement.attributeStyleMap.set('opacity', CSS.number(.5));
myElement.attributeStyleMap.get('opacity'); // CSSUnitValue { value: 0.5, unit: 'number' };
在線demo[10]
使用computedStyleMap
.foo {
transform: translateX(1em) rotate(50deg) skewX(10deg);
vertical-align: baseline;
width: calc(100% - 3em);
}
const cs = document.querySelector('.foo').computedStyleMap();
cs.get('vertical-align');
// CSSKeywordValue {
// value: 'baseline',
// }
cs.get('width');
// CSSMathSum {
// operator: 'sum',
// length: 2,
// values: CSSNumericArray {
// 0: CSSUnitValue { value: -90, unit: 'px' },
// 1: CSSUnitValue { value: 100, unit: 'percent' },
// },
// }
cs.get('transform');
// CSSTransformValue {
// is2d: true,
// length: 3,
// 0: CSSTranslate {
// is2d: true,
// x: CSSUnitValue { value: 20, unit: 'px' },
// y: CSSUnitValue { value: 0, unit: 'px' },
// z: CSSUnitValue { value: 0, unit: 'px' },
// },
// 1: CSSRotate {...},
// 2: CSSSkewX {...},
// }
開發者可以通過這個API實現自己的布局算法,我們可以像原生css一樣使用我們自定義的布局(像display:flex, display:table)。在Masonry layout library[11] 上我們可以看到開發者們是有多想實現各種各樣的復雜布局,其中一些布局光靠 CSS 是不行的。雖然這些布局會讓人耳目一新印象深刻,但是它們的頁面性能往往都很差,在一些低端設備上性能問題猶為明顯。
CSS Layout API 暴露了一個registerLayout方法給開發者,接收一個布局名(layout name)作為后面在 CSS中使用的屬性值,還有一個包含有這個布局邏輯的JavaScript類。
my-div {
display: layout(my-layout);
}
// layout-worklet.js
registerLayout('my-layout', class {
static get inputProperties() { return ['--foo']; }
static get childrenInputProperties() { return ['--bar']; }
async intrinsicSizes(children, edges, styleMap) {}
async layout(children, edges, constraints, styleMap) {}
});
await CSS.layoutWorklet.addModule('layout-worklet.js');
目前瀏覽器大部分還不支持
我們可以在CSS background-image中使用它,我們可以使用Canvas 2d上下文,根據元素的大小控制圖像,還可以使用自定義屬性。
await CSS.paintWorklet.addModule('paint-worklet.js');
registerPaint('sample-paint', class {
static get inputProperties() { return ['--foo']; }
static get inputArguments() { return ['<color>']; }
static get contextOptions() { return {alpha: true}; }
paint(ctx, size, props, args) { }
});
這個API讓我們可以控制基于用戶輸入的關鍵幀動畫,并且以非阻塞的方式。還能更改一個 DOM 元素的屬性,不過是不會引起渲染引擎重新計算布局或者樣式的屬性,比如 transform、opacity 或者滾動條位置(scroll offset)。Animation API的使用方式與 Paint API 和Layout API略有不同我們還需要通過new一個WorkletAnimation來注冊worklet。
// animation-worklet.js
registerAnimator('sample-animator', class {
constructor(options) {
}
animate(currentTime, effect) {
effect.localTime = currentTime;
}
});
await CSS.animationWorklet.addModule('animation-worklet.js');
// 需要添加動畫的元素
const elem = document.querySelector('#my-elem');
const scrollSource = document.scrollingElement;
const timeRange = 1000;
const scrollTimeline = new ScrollTimeline({
scrollSource,
timeRange,
});
const effectKeyframes = new KeyframeEffect(
elem,
// 動畫需要綁定的關鍵幀
[
{transform: 'scale(1)'},
{transform: 'scale(.25)'},
{transform: 'scale(1)'}
],
{
duration: timeRange,
},
);
new WorkletAnimation(
'sample-animator',
effectKeyframes,
scrollTimeline,
{},
).play();
關于此API的更多內容:(https://github.com/w3c/css-houdini-drafts/tree/main/css-animation-worklet-1)
允許開發者自由擴展 CSS 詞法分析器。
解析規則:
const background = window.cssParse.rule("background: green");
console.log(background.styleMap.get("background").value) // "green"
const styles = window.cssParse.ruleSet(".foo { background: green; margin: 5px; }");
console.log(styles.length) // 5
console.log(styles[0].styleMap.get("margin-top").value) // 5
console.log(styles[0].styleMap.get("margin-top").type) // "px"
解析CSS:
const style = fetch("style.css")
.then(response => CSS.parseStylesheet(response.body));
style.then(console.log);
它將提供一些方法來測量在屏幕上呈現的文本元素的尺寸,將允許開發者控制文本元素在屏幕上呈現的方式。使用當前功能很難或無法測量這些值,因此該API將使開發者可以更輕松地創建與文本和字體相關的CSS特性。例如:
Is Houdini ready yet
(https://ishoudinireadyyet.com/)
了解到這里,部分開發者可能會說:“我不需要這些花里胡哨的技術,并不能帶收益。我只想簡簡單單的寫幾個頁面,做做普通的Web App,并不想試圖干預瀏覽器的渲染過程從而實現一些實驗性或炫酷的功能。”如果這樣想的話,我們不妨退一步再去思考。回憶下最近做過的項目,用于實現頁面效果所使用到的技術,grid布局方式在考慮兼容老版本瀏覽器時也不得不放棄。我們想控制瀏覽器渲染頁面的過程并不是僅僅為了炫技,更多的是為了幫助開發者們解決以下兩個問題:
幾年過后再回眸,當主流瀏覽器完全支持Houdini的時候。我們可以在瀏覽器上隨心所欲的使用任何CSS屬性,并且他們都能完美支持。像今天的grid布局在舊版本瀏覽器支持的并不友好的這類問題,那時我們只需要安裝對應的Polyfill就能解決類似的問題。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。