一節聊到正則表達式的簡單應用,不足之處歡迎留言交流。
Javascript正則表達式示例之基本概念
今天,我們來看一下,如何使用正則表達式,匹配HTML標簽及相關信息。
為什么要加上相關信息呢?
因為,如果您想寫一個HTML語法樹解析庫的時候,可能會用到。
下面內容用到的語法
|:表示或者,要么前面,要么后面
(?<=我前面出現的內容)要匹配的內容:只匹配前面出現的字符之后的內容。
可視圖
要匹配的內容(?=我前面出現的內容):只匹配后面出現的字符之前的內容。
可視圖
分組捕獲:一對完整的小括號(),表示一個組。
\數字:你要使用那一個分組捕獲到的內容。
.*?:在正則表達式中,. 表示匹配任意字符,* 表示匹配 0 到任意次的前一個字符,? 表示非貪婪匹配,即盡可能匹配最少的字符。因此,.*? 表示匹配任意字符零次或多次,但盡可能匹配最少的字符。這個表達式通常用于匹配一個字符串中的所有內容,但是避免貪婪匹配導致的匹配錯誤。
^: 表示匹配開始
[要匹配的字符]:只匹配括號中的字符。
比如[0-9]、[a-z]、[A-Z]、[0-9a-zA-Z]、[0-9abc]等等。
[^要匹配的字符]:[]中加^表示匹配不是“要匹配的字符”。
<body><div id="left">left</div><div id="right">right</div></body>
const text = document.body.innerText;
text = text.replace(/\n/g, '');
console.log(text);
//輸出: leftright
假設沒有innerText的功能呢?實現這個功能,使用正則表達式無疑是最方便的。
var text = document.body.innerHTML.replace(/<[^>]+>/g,'');
text = text.replace(/\n/g, '');
console.log(text);
//輸出: leftright
匹配結果
可視圖
是的,這個正則表達式的意思是,查找<>并且包含他們之間不為>的一段字符串。
到這里,您以為就結束了嗎?您在網上搜索匹配HTML標簽,可能也會得到這么一個結果(例如:<[^>]+>、<.*?>、等等),但實際上這只是開始,我們本著只要是程序就可能有bug的原則,所以我們來看下面一個例子。
const strHtml = '<span data-code=">">>是大于符號。</span>';
const strRes = strHtml.replace(/<[^>]+>/g, '');
console.log(strRes);
// ">>是大于符號。
[可憐]bug出現了,怎么辦?別著急,請看下一個知識點。
2.1、首先,我們先解決第一點最后的bug。
const strHtml = '<span data-code=">">>是大于符號。</span>';
// 一個小改動即可。
const strRes = strHtml.replace(/<("[^"]*"|[^>])+>/g, '');
console.log(strRes);
// >是大于符號。
可視圖
完美[打臉] ,還沒結束……
const strHtml = "<span data-code='>'>>是大于符號。</span>";
const strRes = strHtml.replace(/<("[^"]*"|[^>])+>/g, '');
console.log(strRes);
// '>>是大于符號。
甲:這不是我寫的HTML不標準,是你的解析庫兼容性不好,瀏覽器都可以識別,你為什么不可以?
已:……。
const strHtml = `<i code="<"><小于符號。</i><i code='>'>>大于符號。</i>`;
// 繼續改造
const strRes = strHtml.replace(/<((["'])+.*?\2|[^>])+>/g, '');
console.log(strRes);
// <小于符號。>大于符號。
匹配結果
可視圖
是的,利用正則表達式分組捕獲的語法,實現了上面的需求。
2.2 現在,我們來看看,如何找到某個標簽的所有屬性。
const strHtml = `
<input type='text' disabled value="" class="txt txt-md" v-on:click="save('button')" />
`;
上面的例子中,有多種情況,我們首先來整理出來。
屬性1:type='text'
/[\w]+=(["'])+.*?/
屬性2:disabled
/[\w]+/
屬性3:value=""
/[\w]+=(["'])+.*?/
屬性4:class="txt txt-md"
/[\w]+=(["'])+.*?/
屬性5:v-on:click="save('button')"
/[\w:]+=(["'])+.*?/
其他情況:歡迎討論。
把所有情況連起來之后。
const strHtml = `<input type='text' disabled value="" class="txt txt-md" v-on:click="save('button')" />`;
const tagAttrs = strHtml.match(/(?<=\s)[\w:-]+(=(["']).*?\2)*/g) || [];
console.log(tagAttrs);
// ["type='text'", 'disabled', 'value=""', 'class="txt txt-md"', `v-on:click="save('button')"`]
匹配結果
可視圖
人人為我,我為人人,歡迎您的瀏覽,我們一起加油吧。
于前端開發人員來說,css是我們再熟悉不過的朋友的,它就相當于是我們頁面的衣服,頁面好不好看,就看我們css運用的是否爐火純青[小鼓掌][小鼓掌][小鼓掌]。css學起來簡單,但是我們要把它“修煉”到出神入化境界,那這可不是一丁點時間就可以的,需要我們的日積月累,時刻專研。
而今天,就帶給大家一個CSS特效-霓虹燈按鈕,這也是我看到很不錯的效果,帶來分享給大家,希望大家喜歡[送心][送心][送心]
效果如下:
最終效果
那好,廢話不多說,開始我們的CSS代碼。
// 這里我們用div標簽來模擬button按鈕,標簽可以隨意,a、p、span等都可以
// 通常在開發中使用別的標簽來代替button標簽,是因為原始的標簽樣式不好看,
// 我們還得重置樣式,而其他標簽不帶有樣式,我們可以更好的控制自己想要的樣式,
// 當然,button標簽也是可以的,但是如前面所說,原始的樣式需要我們重置。
<div class="btn">button</div>
body {
margin: 0;
padding: 0;
background: #000; // 黑色背景,只為更能突出樣式效果
}
// 初始化按鈕樣式
.btn {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 200px;
height: 60px;
text-align: center;
line-height: 60px;
color: #fff;
font-size: 24px;
font-family: sans-serif;
text-decoration: none;
text-transform: uppercase;
box-sizing: border-box;
// linear-gradient() 漸變屬性,函數用于創建一個表示兩種或多種顏色線性漸變的圖片
background: linear-gradient(90deg, #03a9f4, #f441a5, #ffeb3b, #03a9f4);
background-size: 400%;
border-radius: 30px;
}
初始樣式為這樣:
初始樣式
然后我們給按鈕加上動畫,代碼如下:
.btn:hover {
// linear: 動畫從開始到結束具有相同的速度。
// infinite: 無限次播放
animation: animate 8s linear infinite;
}
@keyframes animate {
0% {
background-position: 0%;
}
100% {
background-position: 400%;
}
}
效果就變為下面這樣:
最后我們給它加上鼠標移上去的效果,代碼如下:
.btn::before {
content: '';
position: absolute;
top: -5px;
left: -5px;
right: -5px;
bottom: -5px;
z-index: -1;
background: linear-gradient(90deg, #03a9f4, #f441a5, #ffeb3b, #03a9f4);
background-size: 400%;
border-radius: 40px;
opacity: 0;
transition: .5s;
}
.btn:hover::before {
filter: blur(20px);
opacity: 1;
animation: animate 8s linear infinite;
}
現在這樣,就是我們的最終效果了:
就此,我們的霓虹燈的按鈕效果就完成了
不足百行,我們就完成了這個效果,以下是我們的CSS的全部代碼:
轉品牌升級后更新了全新的Logo,今天我們用純CSS來實現轉轉的新Logo,為了有一定的挑戰性,這里我們只使用一個標簽實現,將最大化的使用CSS能力完成Logo的繪制與動畫效果。
新logo保留了原本logo里轉轉熊的輪廓,兩個熊耳是兩個衛星圍繞熊頭旋轉,是“循環”的意思。中間傾斜的轉轉首字母“Z”,既像二手質檢的印章,又像N——NEW的首字母,代表著全新的二手生活方式。
以上是我們要還原的Logo效果動圖,現階段使用方式主要是gif和lottie SVG兩種方式。因為我們的目的是使用單標簽實現所有的功能點,對于一些細節部分有所取舍,并不是百分百還原,也并不代表使用CSS的成本和效果是最好的,僅表達CSS的強大能力。接下來分析我們要核心實現的功能點:
基于上述分析接下來開始核心的代碼拆解實現,在開始前先定義一些變量方便后續使用:
:root {
/* 主題色 */
--mainColor: #ff483c;
/* 字體顏色 */
--fontColor: #fff;
/* 字體寬度 */
--zWidth: 260px;
/* 中心橢圓寬高比 */
--parentScaleY: 0.9;
/* 子元素抵消比例 */
--childScaleY: calc(1 / var(--parentScaleY))
}
如果是圍繞一個正圓的旋轉那么實現就簡單很多了,但是這里是一個橢圓,純CSS應該怎么做呢?根據小編目前的了解大概有以下幾種方式都可以實現,但是對應的效果有所區別:
對比各種情況最終使用第三個方案即可滿足條件且實現成本較低,首先畫出一個橢圓的邊框效果,設置scaleY和border-radius將一個正方形變成橢圓形,核心代碼如下:
width: 570px;
aspect-ratio: 1;
border-radius: 50%;
border: 10px solid var(--mainColor);
transform: scaleY(var(--parentScaleY));
然后給這個大圓添加旋轉的動畫,將整體旋轉360度,這時還沒有添加其他的元素,所以界面沒有變化。
@keyframes circle {
0% {
transform: scaleY(var(--parentScaleY)) rotate(0);
}
100% {
transform: scaleY(var(--parentScaleY)) rotate(360deg);
}
}
設置大圓的動畫執行相關參數。
animation: circle 1s 1 cubic-bezier(.5,.08,.52,.93) forwards;
邊框上面的兩個圈基于偽元素實現,繪制一個圓并使用定位將小圓定位于大圓的頂部兩端。然后設置動畫,這里需要注意的是需要設置反向旋轉來抵消父級的旋轉。
@keyframes mini-circle {
0%{
transform: rotate(0deg) scaleY(var(--childScaleY));
}
100%{
transform: rotate(-360deg) scaleY(var(--childScaleY));
}
}
這里為了方便查看將橢圓的參數調大進行對比,可以看到設置抵消后的區別一個圓被壓縮了另一個保持了正常的圓形:
未設置抵消
已設置抵消
這里為了更好的利用元素的使用,這里將兩個圓的繪制進一步優化到一個偽元素中,核心使用徑向漸變背景實現,在同一個 background 中繪制兩個純色圓形,兩個圓除了繪制的位置不同其他都是一樣。代碼如下:
background:
radial-gradient(circle 65px at 31% 24.5%,var(--mainColor) 0% 100%, transparent),
radial-gradient(circle 65px at 72% 24.5%, var(--mainColor) 0% 100%, transparent);
到此這部分的內容基本功能完成,實際效果如下:
接下來使用另一個偽元素實現 Z 字母的效果,仔細觀察 Z 字母的兩個拐角都是銳角效果,并不是日常字母有拐角的效果。
基于當前的樣式我們可以用3段矩形拼接完成效果,上下各一段,中間一段增加旋轉角度,但是只用一個偽元素如何繪制三個矩形呢,還是用到CSS漸變,這次需要用到linear-gradient線性漸變,頂部和底部正常從上往下繪制,中間的部分需要繪制線條的旋轉角度,除開需要顯示的顏色其他部分用#0000透明色,為了方便看效果對三個矩形更換了不同的顏色,代碼如下:
background:
linear-gradient(#f00 25%, #0000 25%),
linear-gradient(#0000 75%, #29eb9a 25%),
linear-gradient(124deg, #0000 40%, #000 40% 60%, #0000 60%);
繪制的效果如下:
可以看到目前的效果還不能滿足需求,兩端都出現了多余的部分,需要進一步優化將其隱藏。這時候需要用到background-size與background-position,通過background-size設置繪制內容的大小,通過設置background-position設置繪制內容的起點位置,因為設置了一定的空隙部分需要增加no-repeat不重復,增加以下代碼:
background-size: 80% var(--w), 80% var(--w), 100% 100%;
background-position: 0 0, 100% 0;
background-repeat: no-repeat;
此時基本符合預期的效果,但實際設計圖左下角的銳角部分有超出正常矩形一部分。
所以需要對剛剛設置的size和position部分改進,將第一個矩形左側空出16px:
background-size: 74% var(--w), 80% var(--w), 100% 100%;
background-position: 16px 0, 100% 0;
因為空出了左側一部分距離,導致整個內容不再是一個正方形,所以需要設置 scaleX 還原寬度將圖像還原到正方形。
對于剛剛設置的background相關屬性可以在代碼層進一步優化,使用簡寫將代碼合并到一行:
background:
linear-gradient(var(--fontColor) 25%, #0000 25%) 16px 0 / 74% var(--zWidth) no-repeat,
linear-gradient(#0000 75%, var(--fontColor) 25%) 100% 0 / 80% var(--zWidth) no-repeat,
linear-gradient(124deg, #0000 40%, var(--fontColor) 40% 60%, #0000 60%) 0 0 / 100% 100% no-repeat;
然后繼續給這個 Z 添加動畫效果,默認設置 opacity: 0 隱藏,因為 Z 是小圓動畫執行結束才出現的,所以還需增加動畫的延遲執行時間,增加動畫相關代碼:
animation: z 0.3s 1s 1 ease-in-out forwards;
opacity: 0;
設置動畫將內容從1.5倍縮小到正常并設置旋轉角度,返抵消以及平移到Logo正中心。這里因為初始增加了1.5的放大所以設置返抵消相關參數有所不同,在設置scaleY的同時還設置了skew進一步還原尺寸。
@keyframes z {
0% {
transform: rotate(-45deg) scale(1.5) translate(0, -50%) skew(-13deg, 8deg);
opacity: 1;
}
100% {
transform: rotate(-42deg) scaleY(var(--childScaleY)) translate(-4%, -64%) skew(-13deg, 8deg);
opacity: 1;
}
}
完成后的 Z 字母動畫效果:
開始動畫時中心的橢圓以及2個圍繞的小圓都有放大的效果,所以需要對前面動畫關鍵幀的定義繼續完善。
小圓部分執行動畫的前10%也增加scale(0.5)。
@keyframes mini-circle {
0%{
transform: rotate(0) scale(0.5);
}
10%{
transform: rotate(0) scaleY(var(--childScaleY));
}
}
大圓執行動畫的前10%部分增加scale(0.8)。大圓部分還有一個效果是字母 Z 出現的時候中心的橢圓由邊框圓變成實心圓,所以是在動畫結束前增加對背景色的變化,代碼如下:
@keyframes circle {
0% {
transform: scale(0.8) rotate(0);
}
10% {
transform: scaleY(var(--parentScaleY)) rotate(0);
}
80% {
background-color: var(--fontColor);
}
100% {
background-color: var(--mainColor);
transform: scaleY(var(--parentScaleY)) rotate(360deg);
}
}
到此我們整個代碼實現過程就結束了,基于一個標簽實現了轉轉的Logo的繪制及動畫效果。當然這只是對其主要的功能還原,如需完整還原細節還需要進一步優化。
CSS的確是足夠強大且對很多復雜的圖形效果都能實現,這里我們主要是使用漸變背景實現圖案的繪制,除了漸變還可以使用CSS陰影也能達到類似的效果。使用CSS對比使用SVG或GIF在資源體積上有很大的提升,本次實現的Logo使用lottie的json需要100KB左右,使用GIF大約需要27KB左右,但是純CSS實現僅1KB不到即可完成,但是對于較為復雜的場景對應的代碼也提升了不少的復雜度,大家要根據實際的情況使用,感興趣的同學歡迎留言交流。
作者:大轉轉FE
來源:微信公眾號:大轉轉FE
出處:https://mp.weixin.qq.com/s/CUfAKou5LEYtwzYB83LWdA
*請認真填寫需求信息,我們會在24小時內與您取得聯系。