Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

有趣的六芒星能力图动画 #228

Open
chokcoco opened this issue Mar 20, 2023 · 4 comments
Open

有趣的六芒星能力图动画 #228

chokcoco opened this issue Mar 20, 2023 · 4 comments

Comments

@chokcoco
Copy link
Owner

chokcoco commented Mar 20, 2023

最近,在看 LPL 比赛的时候,看到这样一个有意思的六芒星能力图动画:

今天,我们就来使用纯 CSS 实现这样一个动画效果!

实现背景网格

对于如下这样一个背景网格,最好的方式当然肯定是切图

如果一定要使用 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

最后

好了,本文到此结束,希望本文对你有所帮助 :)

想 Get 到最有意思的 CSS 资讯,千万不要错过我的公众号 -- iCSS前端趣闻 😄

更多精彩 CSS 技术文章汇总在我的 Github -- iCSS ,持续更新,欢迎点个 star 订阅收藏。

如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。

@miwei230
Copy link

厉害!

@FE-YJP
Copy link

FE-YJP commented Aug 11, 2023

好想用到生产,就是不知道兼容性会不会出问题

@laclys
Copy link

laclys commented Aug 29, 2023

楼主你好 看到这里 想问一下这里

  filter: 
        drop-shadow(0 0 .5px #333)
        drop-shadow(0 0 .5px #333)
        drop-shadow(0 0 .5px #333);

重复三遍 drop-shadow(0 0 .5px #333)是为了加深边框颜色吗

@chokcoco
Copy link
Owner Author

chokcoco commented Aug 31, 2023

@laclys

使用阴影模拟边框的技巧,对边框要求不高的情况下可以使用的一种技巧。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants