使用英文書寫電子郵件或者論文的時(shí)候,我們可能會(huì)因?yàn)樽约翰凰闾叩挠⑽乃交蛘叽中牡确赶乱恍┍容^低的錯(cuò)誤,這或許包括拼寫錯(cuò)誤、語法錯(cuò)誤、 標(biāo)點(diǎn)符號(hào)錯(cuò)誤以及語句結(jié)構(gòu)錯(cuò)誤等。
這肯定不是我們所期望的,于是,如果有一款工具能夠很好地幫助我們檢查并修改這些錯(cuò)誤,我想應(yīng)該會(huì)大受歡迎。
Grammarly就是這樣的一款工具,能夠在我們寫作的時(shí)候?qū)崟r(shí)檢查并顯示出上述中各種類型的錯(cuò)誤,并告知我們?nèi)绾稳ミM(jìn)行修改。它也被稱為是“世界上最好的在線語法檢查工具”,能夠在多個(gè)平臺(tái)上使用,包括網(wǎng)頁版、客戶端、瀏覽器插件等。
2月2日,谷歌公司Project Zero團(tuán)隊(duì)成員Tavis Ormandy在用于Chrome和Firefox瀏覽器的Grammarly插件中發(fā)現(xiàn)了一個(gè)安全漏洞,允許黑客通過任意網(wǎng)站訪問用戶的個(gè)人文件和記錄,受影響的用戶超過2200萬。
Ormandy在一份漏洞報(bào)告中表示, Grammarly插件向所有網(wǎng)站暴露了用戶的登錄令牌信息,這足夠用于登錄到用戶的Ormandy帳戶,并在未經(jīng)許可的情況下訪問用戶的文檔、歷史記錄、日志和其他數(shù)據(jù)。
Ormandy說:“我將其稱之為一個(gè)高危漏洞,因?yàn)檫@嚴(yán)重違背了用戶的期望,沒有任何一位用戶會(huì)期望一個(gè)網(wǎng)站能夠訪問到他們?cè)谄渌W(wǎng)站的創(chuàng)建的文檔或數(shù)據(jù)。”
Ormandy還提供了一份關(guān)于觸發(fā)漏洞的概念驗(yàn)證代碼(PoC),它解釋了如何僅利用四行JavaScript代碼來輕易地觸發(fā)這個(gè)高危漏洞,并竊取Grammarly用戶的登錄令牌。
Grammarly團(tuán)隊(duì)在收到Ormandy通報(bào)的幾小時(shí)內(nèi),就成功地對(duì)其進(jìn)行了修復(fù),Chrome和Firefox瀏覽器用戶目前都可以通過將Ormandy插件更新到最新版本來解決這個(gè)潛在威脅。
此外,一位Grammarly的發(fā)言人強(qiáng)調(diào),目前沒有證據(jù)表明有任何用戶信息已經(jīng)遭到了破壞。
本文由 黑客視界 綜合網(wǎng)絡(luò)整理,圖片源自網(wǎng)絡(luò);轉(zhuǎn)載請(qǐng)注明“轉(zhuǎn)自黑客視界”,并附上鏈接。
TML即一切,所有打算進(jìn)行Web編程的人都應(yīng)該熟悉HTML,并了解如何解析HTML。尤其對(duì)前端工程師來說這更是基礎(chǔ),本文我們就來介紹一下JS下常見的HTML解析庫。
JavaScript和jQuery的DOM操作功能非常適合簡(jiǎn)單HTML片段的解析。在實(shí)際編程中,如果要以編程方式解析DOM完整HTML或XML,則需要一個(gè)更好的解決方案,那就是DOMParser,它是所有現(xiàn)代數(shù)瀏覽器都支持的功能。
通過使用DOMParser,可以輕松解析HTML文檔。但是,一般需要通過欺騙瀏覽器來實(shí)現(xiàn)解析,比如,通過向當(dāng)前文檔添加新元素。
DOMParser的用法非常簡(jiǎn)單明了:
let domParser = new DOMParser();
let doc = domParser.parseFromString(stringContainingXMLSource, "application/xml");
domParser = new DOMParser();
doc = domParser.parseFromString(stringContainingSVGSource, "image/svg+xml");
domParser = new DOMParser();
doc = domParser.parseFromString(stringContainingHTMLSource, "text/html");
專為服務(wù)器設(shè)計(jì)的核心jQuery的快速,靈活和精致的實(shí)現(xiàn)。
Cheerio看起來像jQuery,但是不支持瀏覽器。Cheerio可以解析HTML并使其易于操作,但不會(huì)像瀏覽器中那樣解釋HTML,解析出與瀏覽器不同的內(nèi)容,并且解析的結(jié)果不會(huì)直接發(fā)送給用戶。
Cheerio實(shí)現(xiàn)了jQuery子集,去掉了jQuery中所有與DOM不一致或者是用來填補(bǔ)瀏覽器的東西,重現(xiàn)了jQuery最美妙的API
由于使用了極其簡(jiǎn)潔而又標(biāo)準(zhǔn)的DOM模型, Cheerio對(duì)文檔的轉(zhuǎn)換,操作,渲染都極其的高效。
JavaScript開發(fā)人員都應(yīng)該熟悉Cheerio的語法和用法:
var chro = require('cheerio'),
$ = chio.load('<h1 class="title">Hello World!</h1>');
$('h1.title').text('Hello Chongchong!');
$('h1').attr('id', 'welcome');
$.html();
結(jié)果:
<h1 class="title" id=" welcome ">Hello Chongchong!</h1>
jsdom是很多Web標(biāo)準(zhǔn)(尤其是WHATWG DOM和 HTML 標(biāo)準(zhǔn))純JavaScript實(shí)現(xiàn),可與Node.js結(jié)合使用。jsdom項(xiàng)目的目標(biāo)是模擬Web瀏覽器的子集,從而滿足測(cè)試和抓取實(shí)際的Web應(yīng)用程序。
jsdom不僅僅是HTML解析器,它還可以當(dāng)成瀏覽器。在解析的上下文中,如果要解析的數(shù)據(jù)中省略了必要的標(biāo)記,它會(huì)自動(dòng)添加必要的標(biāo)記。例如,如果沒有html標(biāo)簽,它將像瀏覽器一樣隱式地添加它。
還可以選擇指定一些屬性,例如文檔,引薦來源網(wǎng)址或用戶代理的URL。如果需要解析包含本地URL的鏈接,則該URL特別有用。
由于它實(shí)際上與解析無關(guān),因此只提到j(luò)sdom具有(虛擬)控制臺(tái),對(duì)cookie的支持等。總之,需要模擬瀏覽器環(huán)境
它還可以處理外部資源。如有需求jsdom可以用來加載并執(zhí)行JS腳本。
const jsdom = require("jsdom");
const { JSDOM } = jsdom;
const dom = new JSDOM('<!DOCTYPE html><p>Hello, Chongchong!</p>');
console.log(dom.window.document.querySelector("p").textContent);
結(jié)果:
"Hello, Chongchong!"
parse5
parse5提供了處理HTML時(shí)所需的幾乎所有內(nèi)容。Parse5庫,目標(biāo)是構(gòu)建其他工具,但也可以實(shí)現(xiàn)HTML解析以完成簡(jiǎn)單任務(wù)。Parse5易于使用,但是并不提供瀏覽器為提供的操作DOM的方法(例如getElementById)。
parse5衍生出了一系列采用它的令人印象深刻的項(xiàng)目:jsdom,Angular2和Polymer。如果需求為對(duì)HTML的高級(jí)操作或解析的可靠基礎(chǔ),那么顯然這是一個(gè)不錯(cuò)的選擇。
const parse5 = require('parse5');
const document = parse5.parse('<!DOCTYPE html><html><head></head><body>Hello Chongchong!</body></html>');
console.log(document.childNodes[1].tagName);
本文我們介紹幾個(gè)JS下常見的Html解析庫。根據(jù)標(biāo)準(zhǔn),實(shí)際的HTML格式語法格式是需要容錯(cuò)的。當(dāng)時(shí)這在庫很難簡(jiǎn)單完美的實(shí)現(xiàn)。如果你有更好的推薦,歡迎和大家一起分享。
文,我們將一起學(xué)習(xí),使用純 CSS,實(shí)現(xiàn)如下所示的動(dòng)畫效果:
上面的動(dòng)畫效果,非常有意思,核心有兩點(diǎn):
嗯?很有意思的效果。看上去,我們好像使用 CSS 實(shí)現(xiàn)了碰撞檢測(cè)。
然而,實(shí)際情況真的是這樣嗎?讓我們一起一探究竟!
這里其實(shí)我們并沒有實(shí)現(xiàn)碰撞檢測(cè),因?yàn)樾∏蚝托∏蛑g接觸時(shí),并沒有發(fā)生碰撞效果。
我們只實(shí)現(xiàn)了,小球與邊界之間的碰撞反應(yīng)。不過這里,也并非碰撞檢測(cè),我們只需要設(shè)置好單個(gè)方向的運(yùn)動(dòng)動(dòng)畫,并且設(shè)置 animation-direction: alternate; 即可!
下面,我們一起來實(shí)現(xiàn)單個(gè)方向上的運(yùn)動(dòng)動(dòng)畫:
<div></div>
div {
position: absolute;
top: 0;
left: 0;
width: 100px;
height: 100px;
border-radius: 50%;
background: #0cf;
animation: horizontal 3s infinite linear alternate;
}
@keyframes horizontal {
from {
left: 0;
}
to {
left: calc(100vw - 100px);
}
}
簡(jiǎn)單解讀一下:
這樣,我們就巧妙的實(shí)現(xiàn)了,在視覺上,小球元素移動(dòng)到最右側(cè)邊界時(shí),回彈的效果:
好,有了上面的鋪墊,我們只需要再如法炮制 Y 軸方向的運(yùn)動(dòng)即可。
利用元素的 top 進(jìn)行 Y 軸方向的運(yùn)動(dòng):
div {
position: absolute;
top: 0;
left: 0;
width: 100px;
height: 100px;
border-radius: 50%;
background: #0cf;
animation:
horizontal 3s infinite linear alternate,
vertical 3s infinite linear alternate;
}
@keyframes horizontal {
from {
left: 0;
}
to {
left: calc(100vw - 100px);
}
}
@keyframes vertical {
from {
top: 0;
}
to {
top: calc(100vh - 100px);
}
}
我們?cè)黾恿艘粋€(gè) vertical 3s infinite linear alternate Y 軸的運(yùn)動(dòng)動(dòng)畫,實(shí)現(xiàn)小球從 top: 0 到 top: calc(100vh - 100px); 的運(yùn)動(dòng)。
這樣,我們就成功的得到了 X、Y 兩個(gè)方向上的小球運(yùn)動(dòng),它們疊加在一起的效果如下:
當(dāng)然,此時(shí)的問題在于,缺少了隨機(jī)性,小球的始終在左上和右下角之間來回運(yùn)動(dòng)。
為了解決這個(gè)問題,我們需要添加一定的隨機(jī)性,這個(gè)問題也要解決,我們只需要讓兩個(gè)方向上運(yùn)動(dòng)時(shí)間不一致即可。
我們修改一下代碼,讓 X、Y 軸的運(yùn)動(dòng)時(shí)長(zhǎng)不一致即可:
div {
position: absolute;
// ...
animation:
horizontal 2.6s infinite linear alternate,
vertical 1.9s infinite linear alternate;
}
如此一來,整體的效果就好上了不少,由于整個(gè)動(dòng)畫是無限反復(fù)進(jìn)行的,隨著時(shí)間的推進(jìn),整個(gè)動(dòng)畫呈現(xiàn)出來的就是無序、隨機(jī)的運(yùn)動(dòng):
當(dāng)然,上面的效果基本上沒有什么太大的問題了,但是代碼層面不夠優(yōu)雅,主要有兩點(diǎn)問題:
上述兩個(gè)問題,使用 transform: translate() 都可以解決,但是我們?yōu)槭裁匆婚_始不用 transform 呢?
我們來嘗試一下,使用 transform 替代 top、left:
div {
position: absolute;
top: 0;
left: 0;
width: 100px;
height: 100px;
border-radius: 50%;
background: #0cf;
animation:
horizontal 2.6s infinite linear alternate,
vertical 1.9s infinite linear alternate;
}
@keyframes horizontal {
from { transform: translateX(0); }
to { transform: translateX(calc(100vw - 100%)); }
}
@keyframes vertical {
from { transform: translateY(0); }
to { transform: translateY(calc(100vh - 100%)); }
}
上述代碼中,我們使用了 transform 替代 top、left 運(yùn)動(dòng)。并且,將動(dòng)畫代碼中的 100px 替換成了 100%,這一點(diǎn)的好處是,在 transform: translate 中,100% 表示的是元素本身的高寬,這樣,當(dāng)我們改變?cè)乇旧淼拇笮r(shí),就無需再改變 @keyframes 中的代碼,通用性更強(qiáng)。
我們來看看修改后的效果:
有點(diǎn)問題!預(yù)想中的效果并沒有出現(xiàn),整個(gè)動(dòng)畫只有 Y 軸方向上的動(dòng)畫效果。
這是什么原因呢?
其本質(zhì)在于,定義的 vertical 1.9s infinite linear alternate 的垂直方向的動(dòng)畫效果覆蓋了在其之前定義的 transform: translateX(calc(100vw - 100%)) 動(dòng)畫效果。
說人話就是 X、Y 軸的動(dòng)畫都使用了 transform 屬性,兩者之間造成了沖突。
在之前,這種情況基本是無解的,常見的解決方案就是:
不過,到今天,這個(gè)問題有了更好的解法!也就是 CSS animation 家族中的新屬性 —— animation-composition。
這是一個(gè)非常新的屬性,表示動(dòng)畫合成屬性,從 Chrome 112 版本開始支持。
有三種不同的取值:
{
animation-composition: replace; // 表示動(dòng)畫值替換
animation-composition: add; // 表示動(dòng)畫值追加
animation-composition: accumulate; // 表示動(dòng)畫值累加
}
本文不會(huì)詳細(xì)介紹 animation-composition,感興趣的可以看看 MDN 的屬性介紹或者 XBOXYAN 大佬的這篇文章 -- 了解一下全新的CSS動(dòng)畫合成屬性animation-composition
這里,基于上面的代碼,我們只需要再多設(shè)置一個(gè) animation-composition: accumulate 即可解決問題:
div {
animation:
horizontal 2.6s infinite linear alternate,
vertical 1.9s infinite linear alternate;
animation-composition: accumulate;
}
此時(shí),我們就能通過一個(gè)元素,利用 transform 得到 X、Y 兩個(gè)方向位移動(dòng)畫的合成效果,也就是我們想要的效果:
解決了位移動(dòng)畫的問題,我們就只剩下最后一個(gè)問題了,如何在碰撞的瞬間,實(shí)現(xiàn)顏色的切換?
這里也非常好解決,由于我們是知道每一輪 X、Y 方向上的動(dòng)畫時(shí)長(zhǎng)的,那我們只需要在每次這個(gè)結(jié)點(diǎn)上,切換一次顏色即可。
并且,由于顏色不是過渡變換,而是直接的跳變,所以,我們需要用到 animation 中的 animation-timing-function: steps(),也就是步驟緩動(dòng)函數(shù)。
舉個(gè)例子,假設(shè) X 方向上,單次的動(dòng)畫時(shí)長(zhǎng)為 3s,那我們可以設(shè)置一個(gè) steps(10) 的顏色動(dòng)畫,總時(shí)長(zhǎng)為 30s,這樣,每隔 3s 就會(huì)觸發(fā)一次 steps() 步驟動(dòng)畫,顏色的變化就能夠和小球與邊界的碰撞動(dòng)畫發(fā)生在同一時(shí)刻。
那如何快速實(shí)現(xiàn)顏色的變化呢?利用 filter: hue-rotate() 即可快速實(shí)現(xiàn)顏色的變化。
理解一下下面的代碼:
<div class="normal"></div>
<div class="steps"></div>
div {
width: 200px;
height: 200px;
background: #fc0;
}
.normal {
animation: colorChange 10s linear infinite;
}
.steps {
animation: colorChange 10s steps(5) infinite;
}
@keyframes colorChange {
100% {
filter: hue-rotate(360deg);
}
}
這里,我們用 filter: hue-rotate(360deg) 的改變,實(shí)現(xiàn)顏色的變化,觀察下面的動(dòng)圖,理解 steps(5) 的作用。
效果如下:
理解了這一步,我們就可以把顏色的變化,也一起疊加到上述的小球變化中:
div {
animation:
horizontal 2.6s infinite linear alternate,
vertical 2s infinite linear alternate,
colorX 26s infinite steps(10),
colorY 14s infinite steps(7);
animation-composition: accumulate;
}
@keyframes horizontal {
from { transform: translateX(0); }
to { transform: translateX(calc(100vw - 100%)); }
}
@keyframes vertical {
from { transform: translateY(0); }
to { transform: translateY(calc(100vh - 100%)); }
}
@keyframes colorX {
to {
filter: hue-rotate(360deg);
}
}
@keyframes colorY {
to {
filter: hue-rotate(360deg);
}
}
這樣,我們就成功的得到了題圖中的效果:
完整的代碼,你可以戳這里:Random Circle Path
OK,上面,我們就把整個(gè)效果的完整原理剖析了一遍。
掌握了整個(gè)原理之后,我們就可以把這個(gè)效果應(yīng)用于不同場(chǎng)景中。
譬如,假設(shè)我們有這么一張圖片:
基于上面的效果,稍加改造,我們就可以得到類似的如下效果:
<div></div>
div {
width: 220px;
height: 97px;
background: linear-gradient(#f00, #f00), url(https://s1.ax1x.com/2023/08/15/pPQm9oT.jpg);
background-blend-mode: lighten;
background-size: contain;
animation: horizontal 3.7s infinite -1.4s linear alternate,
vertical 4.1s infinite -2.1s linear alternate,
colorX 37s infinite -1.4s steps(10),
colorY 28.7s infinite -2.1s steps(7);
animation-composition: accumulate;
}
@keyframes horizontal {
from { transform: translateX(0); }
to { transform: translateX(calc(100vw - 100%)); }
}
@keyframes vertical {
from { transform: translateY(0); }
to { transform: translateY(calc(100vh - 100%)); }
}
@keyframes colorX {
to {
filter: hue-rotate(2185deg);
}
}
@keyframes colorY {
to {
filter: hue-rotate(1769deg);
}
}
效果如下:
上面的 DEMO 是基于元素背景色的,本 DEMO 是基于圖片的,因此這里多了一步,利用 mix-blend-mode,實(shí)現(xiàn)了圖片顏色的變化。
完整的代碼,你可以戳這里:CodePen Demo -- Random DVD Path
OK,我們?cè)龠M(jìn)一步,基于上面的效果,我們可以實(shí)現(xiàn)各種有趣的粒子效果,如果同時(shí)讓頁面存在 1000 個(gè)粒子呢?
下面是我使用 CSS-Doodle 實(shí)現(xiàn)的純 CSS 的粒子效果,其核心原理與上面的保持一致,只是添加了更多的隨機(jī)性:
Amazing!是不是非常有趣,整個(gè)效果的代碼基于 CSS-doodle 的語法,不超過 40 行。完整的代碼,你可以戳這里:CSS Doodle - CSS Particles Animation
總結(jié)一下,本文介紹了如何巧妙的利用 CSS 中的各種高階技巧,組合實(shí)現(xiàn)類似于碰撞場(chǎng)景的動(dòng)畫效果。創(chuàng)建出了非常有趣的 CSS 動(dòng)畫,期間各種技巧的組合運(yùn)用,值得好好琢磨學(xué)習(xí)。
鏈接:https://juejin.cn/post/7269797025863499837
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。