英雄聯盟比賽選手的六芒星能力圖動畫是如何製作的?

2023-03-24 12:01:54

最近,在看 LPL 比賽的時候,看到這樣一個有意思的六芒星能力圖動畫:

今天,我們就來使用純 CSS 實現這樣一個動畫效果!

實現背景網格

對於如下這樣一個背景網格,最好的方式當然肯定是切圖,或者使用 SVG 路徑。

如果一定要使用 CSS,勉強也能做,這就涉及了不規則圖形邊框效果,我們有一些方式可以實現,可以參考一下這幾篇文章:

這裡,我們可以使用 drop-shadow(),大致實現一下這個效果,核心步驟:

  1. 通過疊加實現一個六邊形圖形
  2. 利用 drop-shadow() 實現邊框效果

用動圖演示一下,大概是這樣:

程式碼如下:

<div></div>
div {
    position: relative;
    width: 150px;
    height: 260px;
    background: #fff;
    filter: 
        drop-shadow(0 0 .5px #333)
        drop-shadow(0 0 .5px #333)
        drop-shadow(0 0 .5px #333);
    &::before,
    &::after {
        content: "";
        position: absolute;
        inset: 0;
        background: inherit;
    }
    &::before {
        transform: rotate(60deg);
    }
    &::after {
        transform: rotate(-60deg);
    }
}

效果如下:

只需要多疊加幾次,配合 3 條直線,整個背景就能很快的畫出來,完整的程式碼,使用 SASS 表示如下:

<div class="g-container">
    <ul class="g-bg">
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
    </ul>
</div>
.g-container {
    position: relative;
    width: 300px;
    height: 300px;
}
.g-bg {
    position: absolute;
    inset: 0;
    
    &::after {
        content: "";
        position: absolute;
        inset: 20px 0;
        z-index: 6;
        background: 
            linear-gradient(transparent, transparent calc(50% - .5px), #333 calc(50% - .5px), #333 calc(50% + .5px), transparent calc(50% + .5px), transparent),
            linear-gradient(120deg, transparent, transparent calc(50% - 1px), #333 calc(50% - .5px), #333 calc(50% + .5px), transparent calc(50% + 1px), transparent),
            linear-gradient(240deg, transparent, transparent calc(50% - 1px), #333 calc(50% - .5px), #333 calc(50% + .5px), transparent calc(50% + 1px), transparent);
        clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
    }
    
    li {
        --rotate: 0deg;
        position: absolute;
        width: 150px;
        height: 260px;
        translate: -50% -50%;
        left: 50%;
        top: 50%;
        background: #fff;
        filter: 
            drop-shadow(0 0 .5px #333)
            drop-shadow(0 0 .5px #333)
            drop-shadow(0 0 .5px #333);

        &::before,
        &::after {
            content: "";
            position: absolute;
            inset: 0;
            background: inherit;
        }
        &::before {
            transform: rotate(60deg);
        }
        &::after {
            transform: rotate(-60deg);
        }
    }
    @for $i from 1 to 5 {
        li:nth-child(#{$i}) {
            z-index: #{$i};
            width:  #{(1 - $i / 5) * 150}px;
            height: #{(1 - $i / 5) * 260}px;
        }
    }
}

背景網格就出來了:

實現六芒星樣式

有了背景圖,接下來,我們只需要實現六芒星效果圖加上動畫即可。

要實現這麼一個圖形其實非常簡單,利用 clip-path 裁剪即可:

只需要兩步:

  1. 實現一個漸變圖形
  2. 利用 clip-path 進行裁剪

核心程式碼:

<div></div>
···
```CSS
div {
    background: linear-gradient(rgba(241,94,174, .8), rgba(255, 152, 0, .8));
    clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
}

當然,我們可以把座標點當成引數,把座標點計算好後,通過內聯標籤的 style 傳遞進 CSS 中,這樣,就可以展示不同基於的六芒星的圖案。

像是這樣:

<div style="--polygon: 30% 10%, 75% 1%, 94% 51%, 71% 94%, 44% 60%, 8% 50%"></div>
<div style="--polygon: 25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%"></div>
···
```CSS
div {
    background: linear-gradient(rgba(241,94,174, .8), rgba(255, 152, 0, .8));
    clip-path: polygon(var(--polygon));
}

這樣就能快速得到不同的圖形:

藉助 CSS @property 實現動畫 Hover 效果

最後一步,我們只需要實現 Hover 動畫即可。

這裡,我們需要藉助 CSS @property 實現。

關於 CSS @property,還不太瞭解的同學,可以參考:CSS @property,讓不可能變可能

這裡其實就是一個餅圖動畫,首先,我們來實現一個動態的餅圖動畫。

假設,我們有如下結構:

<div></div>
.normal {
    width: 200px;
    height: 200px;
    border-radius: 50%;
    background: conic-gradient(yellowgreen, yellowgreen 25%, transparent 25%, transparent 100%); 
    transition: background 300ms;
    
    &:hover {
        background: conic-gradient(yellowgreen, yellowgreen 60%, transparent 60.1%, transparent 100%); 
    }
}

將會得到這樣一種效果,由於 conic-gradient 是不支援過渡動畫的,得到的是一幀向另外一幀的直接變化:

好,使用 CSS @property 自定義變數改造一下:

@property --per {
  syntax: '<percentage>';
  inherits: false;
  initial-value: 25%;
}

div {
    background: conic-gradient(yellowgreen, yellowgreen var(--per), transparent var(--per), transparent 100%); 
    transition: --per 300ms linear;
    
    &:hover {
        --per: 60%;
    }
}

看看改造後的效果,藉助 CSS @property 自定義變數,我們能夠實現過往無法實現的過渡動畫效果:

CodePode Demo -- conic-gradient 配合 CSS @property 實現餅圖動畫

在本 DEMO 中,我們會運用一樣的技巧,只不過,我們會把 CSS @property 自定義變數運用在 mask 上,通過 mask 的遮罩效果,實現 Hover 過程的展示動畫。

關於 mask,還不太瞭解的同學,可以參考:奇妙的 CSS MASK

核心程式碼如下:

<div class="g-content" style="--polygon: 43% 36%, 69% 12%, 99% 50%, 71% 94%, 30% 90%, 5% 50%"></div>
@property --per {
  syntax: '<percentage> | <angle>';
  inherits: false;
  initial-value: 360deg;
}
.g-content {
    position: absolute;
    inset: 20px 0;
    z-index: 10;
    mask: conic-gradient(#000, #000 var(--per), transparent var(--per), transparent 360deg); 

    &:hover {
        animation: hoverPie 600ms ease-in-out;
    }
    
    &::before {
        content: "";
        position: absolute;
        inset: 0;
        background: linear-gradient(rgba(241,94,174, .8), rgba(255, 152, 0, .8));
        clip-path: polygon(var(--polygon));
    }
}
@keyframes hoverPie {
    0% {
        --per: 0deg;
    }
    100% {
        --per: 360deg;
    }
}

這裡:

  1. 我們用元素的 &::before 實現了我們上述說的六芒星樣式圖
  2. 利用元素本身的 mask 配合一個 CSS @property 屬性實現遮罩動畫

整體 Hover 上去的效果如下:

我們把上述所有的內容融合一下,就能得到完整的效果:

至此,我們就大致還原了整個效果,撒花!

完整的程式碼,你可以戳這裡:CodePen Demo -- LPL Player Hexagram Ability Chart Animation

最後

好了,本文到此結束,希望本文對你有所幫助