溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

好使用純CSS繪制一個中國結(jié)并添加動畫效果

發(fā)布時間:2022-01-27 11:19:50 來源:億速云 閱讀:189 作者:kk 欄目:web開發(fā)

本篇文章為大家展示了好使用純CSS繪制一個中國結(jié)并添加動畫效果,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。

春節(jié)是中國人最重要的節(jié)日,春節(jié)期間的習(xí)俗也非常多,東西南北各不相同。 為了增添年味,過年時家家戶戶會置辦各種年貨和裝飾品,把家里營造得紅紅火火,紅燈籠,紅對聯(lián),紅福字,以及紅色的中國結(jié)。

好使用純CSS繪制一個中國結(jié)并添加動畫效果

中國結(jié)原材料是簡簡單單的紅繩,經(jīng)過古人的巧妙構(gòu)思,編織成一個菱形網(wǎng)格的樣子。網(wǎng)格上的繩線緊緊連接在一起,象征一家人團(tuán)結(jié)和睦,幸福美滿。

好使用純CSS繪制一個中國結(jié)并添加動畫效果

那么如何用CSS來實現(xiàn)一個中國結(jié)呢? 先看最終效果。

好使用純CSS繪制一個中國結(jié)并添加動畫效果


如此 Amazing 的效果,你也可以做出來,下面讓我們開始吧!

一、編碼之前

1. 搜集素材,越簡潔越好

先從網(wǎng)上搜一張中國結(jié)的圖片,中國結(jié)的樣式不止一種,我們選擇一種最經(jīng)典的中國結(jié)的編織樣式。 圖片的質(zhì)量決定了最后成品的質(zhì)量,下面就是一張比較整潔,結(jié)構(gòu)清晰的中國結(jié)圖片。供我們寫CSS時參考使用。

好使用純CSS繪制一個中國結(jié)并添加動畫效果

2. 觀察細(xì)節(jié),構(gòu)思實現(xiàn)的可能性

有了圖片就可以開始寫代碼了嗎?當(dāng)然不是。

首先回想一下現(xiàn)在要做的事:用CSS畫個中國結(jié)。

你真的想好了嗎?這是一個可以實現(xiàn)的目標(biāo)嗎?想象一下,當(dāng)你的領(lǐng)導(dǎo)給你布置一個任務(wù):讓手機(jī)殼根據(jù)APP的主題色而變色。你會直接開始寫代碼嗎?

你會想兩個問題:

  • APP作為一個軟件,是否有和手機(jī)殼互動的接口

  • 手機(jī)殼如果接收到色值,如何變色

這是一個比較極端的例子,上面兩條都無法實現(xiàn)?;氐紺SS和這張中國結(jié)的圖片。我們首先要想的是,我們應(yīng)該用哪些CSS技術(shù),來實現(xiàn)這個圖片。你現(xiàn)在回過頭仔細(xì)觀察一下上面的圖片。

經(jīng)過短暫的觀察,我們發(fā)現(xiàn)這樣一些要點

  • 中國結(jié)的繩子是由漸變色組成,深紅,淺紅,深紅

  • 中間的主體部分由22根相互交叉的繩子組合而成,而且每過一個交叉點就會交換一下層級順序

  • 有一些環(huán)狀結(jié)構(gòu),顏色漸變的過程與直線相同

  • 整體都是紅色,以黃色點綴

然后就是預(yù)想一下實現(xiàn)原理

  • 直線的顏色漸變,使用 linear-gradient 或者 repeating-linear-gradient

  • 環(huán)狀漸變,使用 radial-gradient

  • 網(wǎng)格的交叉,使用 mask 遮罩來達(dá)到交叉效果

  • 四分之三環(huán)以及底部兩根彎曲的繩子使用 clip-path 來裁剪

  • 為了使編碼更方便,采用 SCSS

  • 許多地方可以使用 ::before ::after 實現(xiàn),減少html代碼

3. 結(jié)構(gòu)拆分,化整為零

上面是從技術(shù)角度從整體觀察,下面就是對整個圖片進(jìn)行拆分,先確定其 html 結(jié)構(gòu)。

  • 中間像棋盤一樣的網(wǎng)格結(jié)構(gòu),可以作為一個 html 標(biāo)簽

好使用純CSS繪制一個中國結(jié)并添加動畫效果

  • 四周16個小半圓,使用16個標(biāo)簽定位實現(xiàn)

好使用純CSS繪制一個中國結(jié)并添加動畫效果

  • 兩個四分之三圓,放在一組里,使用相同的樣式,第二個基于第一個旋轉(zhuǎn)180deg

好使用純CSS繪制一個中國結(jié)并添加動畫效果

  • 兩個十字結(jié),樣式一樣,所以也放在一組里

好使用純CSS繪制一個中國結(jié)并添加動畫效果

  • 頂部三個小結(jié)構(gòu),放在一組,外層命名為header

好使用純CSS繪制一個中國結(jié)并添加動畫效果

  • 底部左右兩部分高度相似,也放在一組,命名為footer

好使用純CSS繪制一個中國結(jié)并添加動畫效果

這樣我們得到了 html 的結(jié)構(gòu)

<div class="chinese-knot">
  <div class="grid"></div>
  <div class="ring-small">
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
  </div>
  <div class="ring-big">
    <i><b></b></i>
    <i><b></b></i>
  </div>
  <div class="cross-node">
    <div class="node">
      <i></i>
      <i></i>
      <i></i>
      <i></i>
    </div>
    <div class="node">
      <i></i>
      <i></i>
      <i></i>
      <i></i>
    </div>
  </div>
  <div class="header">
    <i></i>
    <b></b>
    <span></span>
  </div>
  <div class="footer">
    <b></b>
    <b></b>
    <div class="tassels">
      <i></i>
      <i></i>
    </div>
  </div>
</div>

實際編碼當(dāng)中,html 并不是一次寫成,而是經(jīng)過不斷調(diào)整才成為上面這個樣子。

二、CSS逐個實現(xiàn)中國結(jié)部件

1. 網(wǎng)格

網(wǎng)格最終效果是個菱形,也就是正方形旋轉(zhuǎn)了45deg,我們先不旋轉(zhuǎn),看看它是什么樣子

好使用純CSS繪制一個中國結(jié)并添加動畫效果

先設(shè)定一個變量,表示繩子的寬度,我們設(shè)為--width,這個尺寸很重要,后面所有尺寸都是基于這個寬度,這樣后面我們調(diào)整整個圖形的大小,只要改這一個--width就行了。

:root {
  --width: 1.7vh;
}

垂直和水平都各有11根繩,繩子之間的間隙約為繩子寬度的 0.5 倍,所以可以得到網(wǎng)格的寬高都為 11 + 0.5 * 10 = 16 倍的繩子寬度,所以我們可以這樣寫:

:root {
  --width: 1.7vh;
  --grid-width: calc(var(--width) * 16);
}
.grid {
  width: var(--grid-width);
  height: var(--grid-width);
}

body 加上一些樣式,讓盒子居中,再加一個深色背景

body{
  margin: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background: #1d1e22;
  overflow: hidden;
}

再給 .grid 也加一個白色背景色,測試一下:

好使用純CSS繪制一個中國結(jié)并添加動畫效果

這樣屏幕正中間就出現(xiàn)了一個白色方塊,下面我們把白色背景改成11根線的樣式:

:root{
  --width: 1.7vh;
  --red-1: #f40001;
  --red-2: #d40000;
  --red-3: #8c0703;
  --rope: 
    var(--red-3), 
    var(--red-2) calc(var(--width) * 0.25), 
    var(--red-1) calc(var(--width) * 0.45), 
    var(--red-1) calc(var(--width) * 0.55), 
    var(--red-2) calc(var(--width) * 0.75), 
    var(--red-3) var(--width);
  --grid-width: calc(var(--width) * 16);
  --bg-line: linear-gradient(90deg, var(--rope), transparent var(--width)) 0 0 / calc(var(--width) * 1.5) calc(var(--width) * 1.5);
}
.grid{
  width: var(--grid-width);
  height: var(--grid-width);
  background: var(--bg-line);
}

就得到了下面的效果:

好使用純CSS繪制一個中國結(jié)并添加動畫效果

可能你有點蒙圈。發(fā)生了什么事情?

還是讓事情變得簡單點,我們先畫一根不帶漸變的紅線:

.grid{
  background: linear-gradient(
    90deg, 
    var(--red-1), 
    var(--red-1) var(--width), 
    transparent var(--width)
  );
}

好使用純CSS繪制一個中國結(jié)并添加動畫效果

先是一個線性漸變 linear-gradient,然后旋轉(zhuǎn)角度設(shè)為90deg,讓它從左到右漸變(默認(rèn)是從下往上),然后起始值設(shè)為--red-1(你問我red-1red-3哪來的?效果圖上吸來的),在--width處也設(shè)置為--red-1,這樣就得到了一根寬為 --width 的紅線。但這還沒完,得接著在--width 處加一個透明transpanrent,這樣從--width直到圖形的最右側(cè)就都不填充顏色了。

但這不太像根繩子,讓紅線漸變起來:

.grid{
  background: linear-gradient(
    90deg, 
    var(--red-3), 
    var(--red-2) calc(var(--width) * 0.25), 
    var(--red-1) calc(var(--width) * 0.45), 
    var(--red-1) calc(var(--width) * 0.55), 
    var(--red-2) calc(var(--width) * 0.75), 
    var(--red-3) var(--width), 
    transparent var(--width)
  );
}

好使用純CSS繪制一個中國結(jié)并添加動畫效果

這樣就得到了一根有一點點立體效果的繩子??墒窃趺醋屗鼨M向重復(fù)11次,并且間隔0.5倍的--width呢?看下面的代碼:

.grid{
  background: linear-gradient(
    90deg, 
    var(--red-3), 
    var(--red-2) calc(var(--width) * 0.25), 
    var(--red-1) calc(var(--width) * 0.45), 
    var(--red-1) calc(var(--width) * 0.55), 
    var(--red-2) calc(var(--width) * 0.75), 
    var(--red-3) var(--width), 
    transparent var(--width)
  ) 0 0 / calc(var(--width) * 1.5) calc(var(--width) * 1.5);
}

大家來找茬:這段代碼和上一段有什么不同?眼尖的你可能已經(jīng)看出來了,多了這一行:

0 0 / calc(var(--width) * 1.5) calc(var(--width) * 1.5)

/為分界線,左邊的含義是background-positoin,右邊的含義是background-size。

0 0也就是左上角。calc(var(--width) * 1.5) calc(var(--width) * 1.5) 也就是一個正方形,寬度為1.5倍繩寬。

好使用純CSS繪制一個中國結(jié)并添加動畫效果

這樣一個小方塊,在垂直和水平方向上重復(fù),就得了我們想要的結(jié)果:

好使用純CSS繪制一個中國結(jié)并添加動畫效果

可是我們想要的是網(wǎng)格,現(xiàn)在頂多也就算個柵格。

那就使用偽類復(fù)制一份,并且旋轉(zhuǎn)90deg

:root{
  --width: 1.7vh;
  --red-1: #f40001;
  --red-2: #d40000;
  --red-3: #8c0703;
  --rope: 
    var(--red-3), 
    var(--red-2) calc(var(--width) * 0.25), 
    var(--red-1) calc(var(--width) * 0.45), 
    var(--red-1) calc(var(--width) * 0.55), 
    var(--red-2) calc(var(--width) * 0.75), 
    var(--red-3) var(--width);
  --grid-width: calc(var(--width) * 16);
  --bg-line: linear-gradient(90deg, var(--rope), transparent var(--width)) 0 0 / calc(var(--width) * 1.5) calc(var(--width) * 1.5);
}
.grid {
  width: var(--grid-width);
  height: var(--grid-width);
  background: var(--bg-line);
  &:after {
    content: "";
    display: block;
    width: var(--grid-width);
    height: var(--grid-width);
    background: var(--bg-line);
    transform: rotate(90deg);
  }
}

好使用純CSS繪制一個中國結(jié)并添加動畫效果

對比一下參考圖片:

好使用純CSS繪制一個中國結(jié)并添加動畫效果

不能說完全不相干,但是人家一看就經(jīng)過了能工巧匠的編織,咱們這只能算簡單的疊加,怎么才能讓上面變成下面呢?

經(jīng)過仔細(xì)的觀察,發(fā)現(xiàn)只要把上面一層橫著的線,稍加一些遮擋就能實現(xiàn)交叉編織的效果。用哪個css屬性實現(xiàn)呢?那就只有mask 了。

下圖藍(lán)色框是需要遮擋的部分,綠色框是需要重復(fù)的部分。

好使用純CSS繪制一個中國結(jié)并添加動畫效果

仔細(xì)分析一下綠框的構(gòu)成:

好使用純CSS繪制一個中國結(jié)并添加動畫效果

本質(zhì)上是在一個3×3的正方形上挖兩個1×1的小洞,位置分別是0 01.5 1.5。我們要如何畫這樣一張圖?并把這張圖應(yīng)用到mask上呢?

mask是通過傳入的圖片進(jìn)行遮罩處理,而背景圖除了傳入一張png以外,CSS還內(nèi)置了幾個生成背景圖的函數(shù):

  • linear-gradient:線性漸變

  • repeating-linear-gradient:重復(fù)線性漸變

  • radial-gradient:徑向漸變

  • conic-gradient:圓錐漸變

這些函數(shù)都可以和mask配合。這里我們使用conic-gradient實現(xiàn)上面的圖形。

conic-gradient 實現(xiàn)上圖,思路要反著來:不是在方形上挖孔,而是用多個矩形將要渲染的部分填充顏色,剩下的部分自然就是透明的:

好使用純CSS繪制一個中國結(jié)并添加動畫效果

CSS實現(xiàn)如下:

:root{
    ...
    --conic: #000 0 90deg, transparent 0 100%;
}

.grid {
  ...
  &:after {
    ...
    -webkit-mask: conic-gradient(from 0deg at var(--width) calc(var(--width) * 1.5), var(--conic)) 0 0 / calc(var(--width) * 3) calc(var(--width) * 3),
      conic-gradient(from 90deg at calc(var(--width) * 2.5) 0, var(--conic)) 0 0 / calc(var(--width) * 3) calc(var(--width) * 3),
      conic-gradient(from 180deg at calc(var(--width) * 1.5) var(--width), var(--conic)) 0 0 / calc(var(--width) * 3) calc(var(--width) * 3),
      conic-gradient(from 90deg at 0 calc(var(--width) * 2.5), var(--conic)) 0 0 / calc(var(--width) * 3) calc(var(--width) * 3);
  }
}

預(yù)覽效果

好使用純CSS繪制一個中國結(jié)并添加動畫效果

目前為止完整代碼

:root{
  --width: 1.7vh;
  --red-1: #f40001;
  --red-2: #d40000;
  --red-3: #8c0703;
  --rope: 
    var(--red-3), 
    var(--red-2) calc(var(--width) * 0.25), 
    var(--red-1) calc(var(--width) * 0.45), 
    var(--red-1) calc(var(--width) * 0.55), 
    var(--red-2) calc(var(--width) * 0.75), 
    var(--red-3) var(--width);
  --grid-width: calc(var(--width) * 16);
  --bg-line: linear-gradient(90deg, var(--rope), transparent var(--width)) 0 0 / calc(var(--width) * 1.5) calc(var(--width) * 1.5);
  --conic: #000 0 90deg, transparent 0 100%;
}
body{
  margin: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background: #1d1e22;
  overflow: hidden;
}
.grid {
  width: var(--grid-width);
  height: var(--grid-width);
  background: var(--bg-line);
  &:after {
    content: "";
    display: block;
    width: var(--grid-width);
    height: var(--grid-width);
    background: var(--bg-line);
    transform: rotate(90deg);
    -webkit-mask: conic-gradient(from 0deg at var(--width) calc(var(--width) * 1.5), var(--conic)) 0 0 / calc(var(--width) * 3) calc(var(--width) * 3),
      conic-gradient(from 90deg at calc(var(--width) * 2.5) 0, var(--conic)) 0 0 / calc(var(--width) * 3) calc(var(--width) * 3),
      conic-gradient(from 180deg at calc(var(--width) * 1.5) var(--width), var(--conic)) 0 0 / calc(var(--width) * 3) calc(var(--width) * 3),
      conic-gradient(from 90deg at 0 calc(var(--width) * 2.5), var(--conic)) 0 0 / calc(var(--width) * 3) calc(var(--width) * 3);
  }
}
<div class="grid"></div>

沒錯,這個圖形,只用了.grid這一個標(biāo)簽!

但是只有網(wǎng)格還不夠,讓我們繼續(xù)。

2. 半圓環(huán)

回頭看一下參考圖:

好使用純CSS繪制一個中國結(jié)并添加動畫效果

嗯,環(huán)形漸變,那就是radial-gradient了:

  <div class="ring-small">
    <i></i>
  </div>
.ring-small {
  i {
    position: absolute;
    width: calc(var(--width) * 2.5);
    height: calc(var(--width) * 1.5);
    background: radial-gradient(
        circle at 50% 100%, 
        transparent calc(var(--width) * 0.25), 
        var(--red-3) calc(var(--width) * 0.25), 
        var(--red-2) calc(var(--width) * (0.25 + 0.25)),
        var(--red-1) calc(var(--width) * (0.25 + 0.45)), 
        var(--red-1) calc(var(--width) * (0.25 + 0.55)), 
        var(--red-2) calc(var(--width) * (0.25 + 0.75)),
        var(--red-3) calc(var(--width) * (0.25 + 1)), 
        transparent calc(var(--width) * (0.25 + 1))
    );
  }
}

好使用純CSS繪制一個中國結(jié)并添加動畫效果

這樣就得到了半個環(huán)形圖,讓我們使用定位把它和網(wǎng)格結(jié)合看看

/* 先給最外層加個相對定位,后面的絕對定位都相對這一層 */
.chinese-knot {
  width: var(--grid-width);
  height: var(--grid-width);
  position: relative;
}
.ring-small {
  i {
    position: absolute;
    top: calc(var(--width) * -1.5);
    left: calc(var(--width) * 3);
  }
}

好使用純CSS繪制一個中國結(jié)并添加動畫效果

對比素材圖,發(fā)現(xiàn)環(huán)形不是直接緊貼在網(wǎng)格上的,而是先延伸了一小段直線,再接的曲線。那我們就給它增個高吧:

.ring-small {
  i {
    &:before,
    &:after {
      content: "";
      position: absolute;
      bottom: calc(var(--width) * -0.5 + 1px);
      width: var(--width);
      height: calc(var(--width) * 0.5);
      background: var(--bg-line);
    }
    &:after {
      right: 0;
    }
  }
}

上面使用兩個偽類,為半圓環(huán)加了兩截高度為 0.5--width的增高墊,效果如下圖

好使用純CSS繪制一個中國結(jié)并添加動畫效果

接著復(fù)制16個這樣的圖形,分別定位到各自的位置上:

<div class="chinese-knot">
  <div class="grid"></div>
  <div class="ring-small">
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
    <i></i>
  </div>
</div>
.ring-small {
  i {
    position: absolute;
    width: calc(var(--width) * 2.5);
    height: calc(var(--width) * 1.5);
    background: radial-gradient(
        circle at 50% 100%, 
        transparent calc(var(--width) * 0.25), 
        var(--red-3) calc(var(--width) * 0.25), 
        var(--red-2) calc(var(--width) * (0.25 + 0.25)),
        var(--red-1) calc(var(--width) * (0.25 + 0.45)), 
        var(--red-1) calc(var(--width) * (0.25 + 0.55)), 
        var(--red-2) calc(var(--width) * (0.25 + 0.75)),
        var(--red-3) calc(var(--width) * (0.25 + 1)), 
        transparent calc(var(--width) * (0.25 + 1))
    );
    &:before,
    &:after {
      content: "";
      position: absolute;
      bottom: calc(var(--width) * -0.5 + 1px);
      width: var(--width);
      height: calc(var(--width) * 0.5);
      background: var(--bg-line);
    }
    &:after {
      right: 0;
    }
    &:nth-child(-n + 4) {
      top: calc(var(--width) * -2 + 2px);
    }
    &:nth-child(1) {
      left: calc(var(--width) * 3);
    }
    &:nth-child(2) {
      left: calc(var(--width) * 6);
    }
    &:nth-child(3) {
      left: calc(var(--width) * 9);
    }
    &:nth-child(4) {
      left: calc(var(--width) * 12);
    }
    &:nth-child(-n + 8):nth-child(n + 5) {
      bottom: calc(var(--width) * -2 + 2px);
      transform: rotate(180deg);
    }
    &:nth-child(5) {
      left: calc(var(--width) * 1.5);
    }
    &:nth-child(6) {
      left: calc(var(--width) * 4.5);
    }
    &:nth-child(7) {
      left: calc(var(--width) * 7.5);
    }
    &:nth-child(8) {
      left: calc(var(--width) * 10.5);
    }
    &:nth-child(-n + 12):nth-child(n + 9) {
      left: calc(var(--width) * -2.5 + 2px);
      transform: rotate(-90deg);
    }
    &:nth-child(9) {
      top: calc(var(--width) * 3.5);
    }
    &:nth-child(10) {
      top: calc(var(--width) * 6.5);
    }
    &:nth-child(11) {
      top: calc(var(--width) * 9.5);
    }
    &:nth-child(12) {
      top: calc(var(--width) * 12.5);
    }
    &:nth-child(-n + 16):nth-child(n + 13) {
      right: calc(var(--width) * -2.5 + 2px);
      transform: rotate(90deg);
    }
    &:nth-child(13) {
      top: calc(var(--width) * 2);
    }
    &:nth-child(14) {
      top: calc(var(--width) * 5);
    }
    &:nth-child(15) {
      top: calc(var(--width) * 8);
    }
    &:nth-child(16) {
      top: calc(var(--width) * 11);
    }
  }
}

就得到了這樣的效果

好使用純CSS繪制一個中國結(jié)并添加動畫效果

哈哈,很像下水管道~

3. 四分之三圓環(huán)

還是先看素材:

好使用純CSS繪制一個中國結(jié)并添加動畫效果

嗯,不得不懷疑網(wǎng)易云的 LOGO 的靈感是不是就是中國結(jié)。

好使用純CSS繪制一個中國結(jié)并添加動畫效果

單個環(huán)形已經(jīng)實現(xiàn)了,兩個環(huán)也不難吧:

<div class="ring-big">
    <i><b></b></i>
</div>
.ring-big {
  i {
    position: absolute;
    width: calc(var(--width) * 6);
    height: calc(var(--width) * 6);
    b {
      position: absolute;
      left: 0;
      top: 0;
      width: 100%;
      height: 100%;
      background: radial-gradient(
        circle at 50% 50%,
        transparent calc(var(--width) * 0.5),
        var(--red-3) calc(var(--width) * 0.5),
        var(--red-2) calc(var(--width) * (0.5 + 0.25)),
        var(--red-1) calc(var(--width) * (0.5 + 0.45)),
        var(--red-1) calc(var(--width) * (0.5 + 0.55)),
        var(--red-2) calc(var(--width) * (0.5 + 0.75)),
        var(--red-3) calc(var(--width) * (0.5 + 1)),
        transparent calc(var(--width) * (0.5 + 1)),
        transparent calc(var(--width) * 2),
        var(--red-3) calc(var(--width) * 2),
        var(--red-2) calc(var(--width) * (2 + 0.25)),
        var(--red-1) calc(var(--width) * (2 + 0.45)),
        var(--red-1) calc(var(--width) * (2 + 0.55)),
        var(--red-2) calc(var(--width) * (2 + 0.75)),
        var(--red-3) calc(var(--width) * (2 + 1)),
        transparent calc(var(--width) * (2 + 1))
      );
    }
  }
}

好使用純CSS繪制一個中國結(jié)并添加動畫效果

為什么 <i> 標(biāo)簽里要再套一個標(biāo)簽?zāi)兀驗榻酉聛砦覀円獔?zhí)行 clip-path,還要給圓環(huán)增高,而clip-path 會給增高的部分也裁剪掉,所以只能再套一層,讓內(nèi)層的 <b> 自己 clip,增高則使用 <i> 的偽類實現(xiàn)。下面就是將圓環(huán)右下角 1/4 裁剪掉并且加一個增高墊的代碼:

.ring-big {
  i {
    ...
    b {
      ...
      clip-path: polygon(0 0, 100% 0, 100% 50%, 50% 50%, 50% 100%, 0 100%);
    }
    &:before,
    &:after {
      content: "";
      position: absolute;
      top: calc(var(--width) * 3 - 1px);
      left: calc(var(--width) * 3.5);
      width: calc(var(--width) * 2.5);
      height: calc(var(--width) * 0.5 + 2px);
      background: repeating-linear-gradient(
        90deg, 
        var(--red-3), 
        var(--red-2) calc(var(--width) * 0.25), 
        var(--red-1) calc(var(--width) * 0.45), 
        var(--red-1) calc(var(--width) * 0.55), 
        var(--red-2) calc(var(--width) * 0.75), 
        var(--red-3) var(--width), 
        transparent var(--width), 
        transparent calc(var(--width) * 1.5)
      );
    }
    &:after {
      transform: rotate(90deg);
      transform-origin: left top;
      top: calc(var(--width) * 3.5);
      left: calc(var(--width) * 3.5 + 1px);
    }
  }
}

好使用純CSS繪制一個中國結(jié)并添加動畫效果

復(fù)制一份并定位:

.ring-big {
  i {
    ...
    &:nth-child(1) {
      left: calc(var(--width) * -3.5);
      top: calc(var(--width) * -3.5);
    }
    &:nth-child(2) {
      left: auto;
      top: auto;
      right: calc(var(--width) * -3.5);
      bottom: calc(var(--width) * -3.5);
      transform: rotate(180deg);
    }
  }
}

好使用純CSS繪制一個中國結(jié)并添加動畫效果

到這里,工作的一半就已經(jīng)完成了~繼續(xù)

4. 十字結(jié)

好使用純CSS繪制一個中國結(jié)并添加動畫效果

這個圖形,相對于上面幾個,已經(jīng)沒什么難度了,五個1×1 的正方形,中間的漸變方向和周圍四個垂直。

中間的正方形,用父級本身實現(xiàn),里面周圍四個,用四個子<i>標(biāo)簽實現(xiàn):

<div class="cross-node">
    <div class="node">
      <i></i>
      <i></i>
      <i></i>
      <i></i>
    </div>
    <div class="node">
      <i></i>
      <i></i>
      <i></i>
      <i></i>
    </div>
  </div>
.cross-node {
  .node {
    position: absolute;
    z-index: 2;
    width: var(--width);
    height: var(--width);
    background: var(--bg-line);
    i {
      position: absolute;
      width: var(--width);
      height: var(--width);
      background: var(--bg-line);
      transform: rotate(90deg);
      &:nth-child(1) {
        left: calc(var(--width) * -1);
      }
      &:nth-child(2) {
        left: var(--width);
      }
      &:nth-child(3) {
        top: calc(var(--width) * -1);
      }
      &:nth-child(4) {
        top: var(--width);
      }
    }
    &:nth-child(1) {
      right: calc(var(--width) * -1);
      top: calc(var(--width) * -1);
    }
    &:nth-child(2) {
      left: calc(var(--width) * -1);
      bottom: calc(var(--width) * -1);
    }
  }
}

好使用純CSS繪制一個中國結(jié)并添加動畫效果

好使用純CSS繪制一個中國結(jié)并添加動畫效果

5. 掛繩

前面我們都是讓中國結(jié)處于一個斜躺的姿態(tài),寫頭部和尾部之前,讓我們先把它擺正:

.chinese-knot {
  ...
  transform: rotate(-45deg) translate(calc(var(--width) * 4), calc(var(--width) * -4));
}

好使用純CSS繪制一個中國結(jié)并添加動畫效果

回頭看素材圖:

好使用純CSS繪制一個中國結(jié)并添加動畫效果

先確定一下html結(jié)構(gòu):

<div class="header">
    <i></i>
    <b></b>
    <span></span>
</div>

i 是上面的吊繩,b 是圓環(huán),span 是銜接處的短繩,帶點黃色裝飾。為了方便調(diào)整定位,我們從下往上實現(xiàn),先寫短繩:

:root {
  --yellow-1: #fced00;
  --yellow-2: #f28a00;
  --yellow-3: #da571b;
  --bg-yellow: linear-gradient(
    90deg,
    var(--yellow-3),
    var(--yellow-2) 20%,
    var(--yellow-1) 40%,
    var(--yellow-1) 60%,
    var(--yellow-2) 80%,
    var(--yellow-3) 100%
  );
}
.header {
  position: absolute;
  right: 0;
  top: 0;
  transform: rotate(45deg);
  i {
    position: absolute;
    bottom: calc(var(--width) * 1);
    left: calc(var(--width) * -0.5);
    width: calc(var(--width) * 1);
    height: calc(var(--width) * 2);
    background: var(--bg-line);
    &:before {
      content: "";
      display: block;
      height: calc(var(--width) * 0.5);
      background: var(--bg-yellow);
    }
  }
}

然后是圓環(huán):

.header {
  ...
  b {
    position: absolute;
    bottom: calc(var(--width) * 3);
    left: calc(var(--width) * -1.5);
    width: calc(var(--width) * 3);
    height: calc(var(--width) * 3);
    background: radial-gradient(
      circle at 50%,
      transparent calc(var(--width) * 0.75),
      var(--red-3) calc(var(--width) * 0.75),
      var(--red-2) calc(var(--width) * (0.75 + 0.15)),
      var(--red-1) calc(var(--width) * (0.75 + 0.3)),
      var(--red-1) calc(var(--width) * (0.75 + 0.45)),
      var(--red-2) calc(var(--width) * (0.75 + 0.6)),
      var(--red-3) calc(var(--width) * (0.75 + 0.75)),
      transparent calc(var(--width) * (0.75 + 0.75))
    );
  }
}

最后是長的吊繩:

.header {
  ...
  span {
    position: absolute;
    bottom: calc(var(--width) * 5);
    left: calc(var(--width) * -0.25);
    width: calc(var(--width) * 0.5);
    height: calc(var(--width) * 30);
    background: linear-gradient(90deg, var(--red-2), var(--red-1) 20%, var(--red-2) 70%, var(--red-3));
    border-radius: calc(var(--width) * 0.25);
  }
}

單獨效果

好使用純CSS繪制一個中國結(jié)并添加動畫效果

整體效果

好使用純CSS繪制一個中國結(jié)并添加動畫效果

6. 流蘇

好使用純CSS繪制一個中國結(jié)并添加動畫效果

確定html結(jié)構(gòu):

<div class="footer">
    <b></b>
    <b></b>
    <div class="tassels">
      <i></i>
      <i></i>
    </div>
</div>

可以看到,流蘇部分,有兩個彎曲的 1/8 環(huán),我們用兩個b 標(biāo)簽來表示。這個形狀依然還是先畫一個完整的環(huán),然后裁剪來實現(xiàn):

.footer {
  position: absolute;
  left: 0;
  bottom: 0;
  b {
    position: absolute;
    width: calc(var(--width) * 15);
    height: calc(var(--width) * 15);
    background: radial-gradient(
      circle at 50%,
      transparent calc(var(--width) * 6.5),
      var(--red-3) calc(var(--width) * 6.5),
      var(--red-2) calc(var(--width) * (6.5 + 0.25)),
      var(--red-1) calc(var(--width) * (6.5 + 0.45)),
      var(--red-1) calc(var(--width) * (6.5 + 0.55)),
      var(--red-2) calc(var(--width) * (6.5 + 0.75)),
      var(--red-3) calc(var(--width) * (6.5 + 1)),
      transparent calc(var(--width) * (6.5 + 1))
    );
  }
}

好使用純CSS繪制一個中國結(jié)并添加動畫效果

加上裁剪并定位:

.footer {
  ...
  b {
    ...
    &:nth-child(1) {
      left: calc(var(--width) * -8.5);
      top: calc(var(--width) * 1);
      clip-path: polygon(50% 0, 50% 50%, 10% 0);
    }
    &:nth-child(2) {
      left: calc(var(--width) * -16);
      top: calc(var(--width) * -6.5);
      clip-path: polygon(100% 50%, 50% 50%, 100% 90%);
    }
  }
}

好使用純CSS繪制一個中國結(jié)并添加動畫效果

兩個小尾巴就實現(xiàn)了。

最后是流蘇。先畫一下背景上的垂直細(xì)線,這里我們用 repeating-linear-gradient 實現(xiàn),每隔 2px 畫一條 1px 寬的透明度為 0.2 的黑線:

.footer {
  .tassels {
    i {
      position: absolute;
      width: calc(var(--width) * 2.5);
      height: calc(var(--width) * 14);
      background: var(--red-2) repeating-linear-gradient(90deg, rgba(0, 0, 0, 0.2) 0, rgba(0, 0, 0, 0.2) 1px, transparent 1px, transparent 3px) 50% 50% / 3px 1px;}
  }
}

好使用純CSS繪制一個中國結(jié)并添加動畫效果

再蒙上一層黃色的裝飾:

.footer {
  .tassels {
    i {
      ...
      &:before {
        content: "";
        position: absolute;
        top: calc(var(--width) * 0.5);
        width: 100%;
        height: calc(var(--width) * 3.6);
        background: var(--bg-yellow);
        clip-path: polygon(0 0, 100% 0, 100% 10%, 0 10%, 0 15%, 100% 15%, 100% 85%, 0 85%, 0 90%, 100% 90%, 100% 100%, 0 100%, 0 0);
      }
  }
}

好使用純CSS繪制一個中國結(jié)并添加動畫效果

上面代碼中使用 clip-path 對黃色背景裁剪,露出兩條紅線,裁剪路徑可以用下圖表示:

好使用純CSS繪制一個中國結(jié)并添加動畫效果

最終效果:

好使用純CSS繪制一個中國結(jié)并添加動畫效果

三、加點動畫

本來到這里就應(yīng)該結(jié)束了。但是我想讓這個中國結(jié)有點實際用途,比如加點交互什么的。

紅包也是春節(jié)的習(xí)俗之一,那就加一個拉一下中國結(jié)掉落紅包雨的特效吧~

1. 拉一下

給中國結(jié)在:active狀態(tài)下加個位移即可實現(xiàn):

.chinese-knot {
  width: var(--grid-width);
  height: var(--grid-width);
  position: relative;
  transform: rotate(-45deg) translate(calc(var(--width) * 4), calc(var(--width) * -4));
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: all 0.5s;
  &:active {
    transform: rotate(-45deg) translate(calc(var(--width) * 2), calc(var(--width) * -2));
  }
}

好使用純CSS繪制一個中國結(jié)并添加動畫效果

2. 畫個紅包

先搜索一個紅包素材:

好使用純CSS繪制一個中國結(jié)并添加動畫效果

觀察一下紅包結(jié)構(gòu),深紅背景,淺紅弧形開口,加一個黃色圓形封口,上面寫著一個繁體的開字。

我們可以先確定 html 結(jié)構(gòu)。.rain 作為外層,代表整個紅包雨,一個i標(biāo)簽代表一個紅包:

<div class="rain">
  <i></i>
</div>

一個標(biāo)簽怎么實現(xiàn)上面提到的三種元素呢?看代碼:

.rain {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  display: flex;
  justify-content: space-around;
  i {
    position: relative;
    display: block;
    width: calc(var(--width) * 5);
    height: calc(var(--width) * 8);
    background: var(--red-3);
    border-radius: calc(var(--width) * 0.4);
    overflow: hidden;
    box-shadow: 0 calc(var(--width) * 1) calc(var(--width) * 1) rgba(0, 0, 0, 0.3);
    &:before {
      content: "";
      position: absolute;
      left: 50%;
      transform: translate(-50%, -50%);
      width: calc(var(--width) * 8);
      height: calc(var(--width) * 8);
      background: var(--red-1);
      opacity: 0.5;
      border-radius: 50%;
    }
    &:after {
      content: "開";
      position: absolute;
      left: 50%;
      transform: translate(-50%, 140%);
      width: calc(var(--width) * 2);
      height: calc(var(--width) * 2);
      background: var(--yellow-2);
      border-radius: 50%;
      display: flex;
      align-items: center;
      justify-content: center;
      font-style: normal;
      font-size: calc(var(--width) * 0.5);
      color: var(--yellow-1);
      text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.1);
    }
  }
}

好使用純CSS繪制一個中國結(jié)并添加動畫效果

使用i標(biāo)簽自身實現(xiàn)紅包主體,:before 偽類實現(xiàn)弧形的開口,:after 偽類實現(xiàn)黃色圓形封口,在content中寫上字。

一個紅包完成了,再復(fù)制 9 個:

<div class="rain">
  <i></i>
  <i></i>
  <i></i>
  <i></i>
  <i></i>
  <i></i>
  <i></i>
  <i></i>
  <i></i>
  <i></i>
</div>

好使用純CSS繪制一個中國結(jié)并添加動畫效果

這樣就得到了 10 個固定在頂部,并且整齊排列的紅包了。

3. 紅包雨動畫

下雨嘛,從上往下運動就好了:

.rain {
  ...
  i {
    ...
    animation: fall 3s ease-in infinite;
  }
}
@keyframes fall {
  0% {
    transform: translate(0, 0);
  }
  100% {
    transform: translate(0, 100vh);
  }
}

好使用純CSS繪制一個中國結(jié)并添加動畫效果

聰明的你估計已經(jīng)猜到了這樣的結(jié)果:誰家的雨是這樣齊刷刷的下來的?

那我們就紅包的垂直位置錯落一點,使用 sassrandom 函數(shù)來實現(xiàn)隨機(jī):

.rain {
  ...
  i {
    ...
    @for $i from 1 through 10 {
      &:nth-child(#{$i}) {
        top: random(60) + vh;
      }
    }
  }
}

好使用純CSS繪制一個中國結(jié)并添加動畫效果

額,效果怎么和想象的不一樣。依舊還是齊刷刷下落,只不過是"錯落"的齊刷刷。

那我們讓每個紅包的開始時間也隨機(jī)不就行了嘛:

.rain {
  ...
  i {
    ...
    @for $i from 1 through 10 {
      &:nth-child(#{$i}) {
        top: random(60) + vh;
        animation-delay: random(30) * 0.1s;
      }
    }
  }
}

好使用純CSS繪制一個中國結(jié)并添加動畫效果

嗯,好了一點點。但是有一個問題,屏幕上的雨點,有時候很多,有時候很少,不夠均勻。那我們把動畫的持續(xù)時間也隨機(jī)會怎么樣呢?

.rain {
  ...
  i {
    ...
    @for $i from 1 through 10 {
      &:nth-child(#{$i}) {
        top: random(60) + vh;
        animation-delay: random(30) * 0.1s;
        animation-duration: random(10) * 0.1s + 2s; /* 2s ~ 3s 之間隨機(jī) */
      }
    }
  }
}

好使用純CSS繪制一個中國結(jié)并添加動畫效果

終于更像雨了~

但是現(xiàn)在雨滴是憑空出現(xiàn)的,很生硬,我們只要把開始的位置挪到負(fù)一屏,然后讓它下落到正二屏就行了:

.rain {
  ...
  top: -100vh;
}
@keyframes fall {
  0% {
    transform: translate(0, 0);
  }
  100% {
    transform: translate(0, 200vh);
  }
}

好使用純CSS繪制一個中國結(jié)并添加動畫效果

這樣就有了源源不斷下落的效果。

4. 拉一下觸發(fā)紅包雨

CSS 不是 JS ,怎么觸發(fā)點擊事件呢?

我們就要運用 CSS 本身的特性了,checkbox 復(fù)選框有個選中狀態(tài) :checked,而復(fù)選框可以用點擊切換這個狀態(tài),再使用 CSS 的兄弟選擇器 element ~ element 即可實現(xiàn)點擊添加樣式的效果。

樣式可以觸發(fā)了,那如何觸發(fā)動畫呢?

animation 屬性添加到元素上后,播放狀態(tài)默認(rèn)是 running ,我們需要先把初始播放狀態(tài)改為 paused (暫停), 然后通過上面的方法,把元素的播放狀態(tài)改回 running 來實現(xiàn)播放動畫的效果:

<input type="checkbox" id="switch">
<label class="chinese-knot" for="switch">...</label>
<div class="rain">...</div>
.rain {
  ...
  i {
    ...
    animation: fall 3s ease-in infinite;
    /* 默認(rèn)不播放動畫 */
    animation-play-state: paused;
  }
}

#switch {
  visibility: hidden;
  pointer-events: none;
}
/* checkbox 選中時播放動畫 */
#switch:checked ~ .rain i {
  animation-play-state: running;
}
/* 點擊時重置動畫,否則取消checkbox選中狀態(tài),動畫會中止并停留在當(dāng)前位置 */
.chinese-knot:active ~ .rain i {
  animation: none;
}

上面的 html 中,我們讓.chinese-knotdiv 改為 label 來指向 checkbox,方法是 labelforcheckboxid 設(shè)為相同的值。

好使用純CSS繪制一個中國結(jié)并添加動畫效果

效果很不錯,我們再給紅包雨下落時加個背景,以提醒用戶當(dāng)前的狀態(tài)。并且下紅包雨時,調(diào)低中國結(jié)的透明度,以突出紅包的存在感。

<input type="checkbox" id="switch">
<div class="bg"></div>
<label class="chinese-knot" for="switch">...</label>
<div class="rain">...</div>
.bg {
  position: absolute;
  left: 0;
  top: 0;
  height: 100vh;
  width: 100vw;
  background: linear-gradient(0deg, #171a4b, #96367f);
  opacity: 0;
  transition: all 0.5s;
}
#switch:checked ~ .bg {
  opacity: 1;
}
#switch:checked ~ .chinese-knot {
  opacity: 0.2;
  &:hover {
    opacity: 0.5;
  }
}

好使用純CSS繪制一個中國結(jié)并添加動畫效果

css的基本語法是什么

css的基本語法是:1、css規(guī)則由選擇器和一條或多條聲明兩個部分構(gòu)成;2、選擇器通常是需要改變樣式的HTML元素;3、每條聲明由一個屬性和一個值組成;4、屬性和屬性值被冒號分隔開。

上述內(nèi)容就是好使用純CSS繪制一個中國結(jié)并添加動畫效果,你們學(xué)到知識或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識儲備,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

css
AI