zoukankan      html  css  js  c++  java
  • 如何用 CSS 和 D3 创作旋臂粒子动画

    效果预览

    在线演示

    按下右侧的“点击预览”按钮可以在当前页面预览,点击链接可以全屏预览。

    https://codepen.io/comehope/pen/xJrOqd

    可交互视频

    此视频是可以交互的,你可以随时暂停视频,编辑视频中的代码。

    请用 chrome, safari, edge 打开观看。

    https://scrimba.com/p/pEgDAM/cr6Vetm

    源代码下载

    本地下载

    每日前端实战系列的全部源代码请从 github 下载:

    https://github.com/comehope/front-end-daily-challenges

    代码解读

    定义 dom,容器中包含 6 个 内含 <span><div> 元素,每个 <div> 元素代表 1 个粒子:

    &lt;section class="container"&gt;
        &lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
        &lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
        &lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
        &lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
        &lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
        &lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
    &lt;/section&gt;
    

    居中显示:

    body {
        margin: 0;
        height: 100vh;
        display: flex;
        align-items: center;
        justify-content: center;
        background-color: black;
    }
    

    定义容器尺寸:

    .container {
         70vmin;
        height: 70vmin;
    }
    

    在容器中定位 <div>,并在 <div> 中用 <span> 画出粒子:

    .container {
        display: flex;
        align-items: center;
        justify-content: center;
    }
    
    .container div {
        position: absolute;
         10vmin;
        height: 10vmin;
    }
    
    .container div span {
        position: absolute;
         inherit;
        height: inherit;
        border-radius: 50%;
        background-color: limegreen;
        transform: translateX(300%);
    }
    

    用变量定义粒子的旋转角度,其中 --particles-per-circle 每圈的粒子数,因为每圈有 3 个粒子,所以圈中有 3 个位置,每个位置有 2 个粒子重叠在一起,此时看起来是只有 3 个粒子的样子:

    .container {
        --particles-per-circle: 3;
    }
    
    .container div {
        transform: rotate(calc(var(--n) / var(--particles-per-circle) * -360deg));
    }
    
    .container div:nth-child(1) {
        --n: 1;
    }
    
    .container div:nth-child(2) {
        --n: 2;
    }
    
    .container div:nth-child(3) {
        --n: 3;
    }
    
    .container div:nth-child(4) {
        --n: 4;
    }
    
    .container div:nth-child(5) {
        --n: 5;
    }
    
    .container div:nth-child(6) {
        --n: 6;
    }
    

    定义粒子从中心向外侧的运动效果:

    .container div span {
        animation: move 2s linear infinite;
    }
    
    @keyframes move {
        from {
            transform: translateX(0) scale(0);
        }
    
        70% {
            transform: translateX(210%) scale(0.55);
        }
    
        to {
            transform: translateX(300%) scale(0);
        }
    }
    

    再增加运动时让粒子变色的效果,沿色相环取了 10 个颜色:

    .container div span {
        animation: 
            move 2s linear infinite,
            change-color 2s linear infinite;
    }
    
    @keyframes change-color {
        0%, 100% {
            background-color: hsl(calc(0 / 100 * 360deg), 80%, 55%);
        }
    
        10% {
            background-color: hsl(calc(10 / 100 * 360deg), 80%, 55%);
        }
    
        20% {
            background-color: hsl(calc(20 / 100 * 360deg), 80%, 55%);
        }
    
        30% {
            background-color: hsl(calc(30 / 100 * 360deg), 80%, 55%);
        }
    
        40% {
            background-color: hsl(calc(40 / 100 * 360deg), 80%, 55%);
        }
    
        50% {
            background-color: hsl(calc(50 / 100 * 360deg), 80%, 55%);
        }
    
        60% {
            background-color: hsl(calc(60 / 100 * 360deg), 80%, 55%);
        }
    
        70% {
            background-color: hsl(calc(70 / 100 * 360deg), 80%, 55%);
        }
    
        80% {
            background-color: hsl(calc(80 / 100 * 360deg), 80%, 55%);
        }
    
        90% {
            background-color: hsl(calc(90 / 100 * 360deg), 80%, 55%);
        }
    }
    

    用变量设置动画延时,这时可以看到 6 个粒子陆续出现了。其中 --circles 表示圈数;--particles 表示粒子数,它等于每圈的粒子数与圈数的积:

    .container {
        --circles: 2;
        --particles: calc(var(--particles-per-circle) * var(--circles));
    }
    
    .container div span {
        animation-delay: calc(var(--n) / var(--particles) * -2s);
    }
    

    接下来用 d3 来批量创建粒子。
    引入 d3 库:

    &lt;script src="https://d3js.org/d3.v5.min.js"&gt;&lt;/script&gt;
    

    用 d3 为 css 的 --particles-per-circle 和 --circles 变量赋值:

    const PARTICLES_PER_CIRCLE = 3;
    const CIRCLES = 2;
    
    d3.select('.container')
        .style('--particles-per-circle', PARTICLES_PER_CIRCLE)
        .style('--circles', CIRCLES);
    

    用 d3 创建粒子 dom 元素:

    const COUNT_OF_PARTICLES = PARTICLES_PER_CIRCLE * CIRCLES;
    
    d3.select('.container')
        .style('--particles-per-circle', PARTICLES_PER_CIRCLE)
        .style('--circles', CIRCLES)
        .selectAll('div')
        .data(d3.range(COUNT_OF_PARTICLES))
        .enter()
        .append('div')
        .append('span');
    

    用 d3 为粒子元素的 --n 变量赋值:

    d3.select('.container')
        .style('--particles-per-circle', PARTICLES_PER_CIRCLE)
        .style('--circles', CIRCLES)
        .selectAll('div')
        .data(d3.range(COUNT_OF_PARTICLES))
        .enter()
        .append('div')
        .style('--n', (d) =&gt; d + 1)
        .append('span');
    

    删除掉 dom 中的粒子元素,以及用 css 声明的变量。

    最后,调整每圈的粒子数和圈数,形成旋臂效果:

    const PARTICLES_PER_CIRCLE = 14;
    const CIRCLES = 4;
    

    大功告成!

    原文地址:https://segmentfault.com/a/1190000015755660
  • 相关阅读:
    PAT Advanced 1067 Sort with Swap(0, i) (25分)
    PAT Advanced 1048 Find Coins (25分)
    PAT Advanced 1060 Are They Equal (25分)
    PAT Advanced 1088 Rational Arithmetic (20分)
    PAT Advanced 1032 Sharing (25分)
    Linux的at命令
    Sublime Text3使用指南
    IntelliJ IDEA创建第一个Groovy工程
    Sublime Text3 安装ftp插件
    Sublime Text3配置Groovy运行环境
  • 原文地址:https://www.cnblogs.com/lalalagq/p/10077908.html
Copyright © 2011-2022 走看看