如何用 CSS 和 D3 创作旋臂粒子动画

简介: 效果预览在线演示按下右侧的“点击预览”按钮可以在当前页面预览,点击链接可以全屏预览。https://codepen.io/comehope/pen/xJrOqd可交互视频此视频是可以交互的,你可以随时暂停视频,编辑视频中的代码。

在这里插入图片描述

效果预览

在线演示

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

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 {
    width: 70vmin;
    height: 70vmin;
}

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

.container {
    display: flex;
    align-items: center;
    justify-content: center;
}

.container div {
    position: absolute;
    width: 10vmin;
    height: 10vmin;
}

.container div span {
    position: absolute;
    width: 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
相关文章
|
前端开发 JavaScript
CSS 过渡和动画
CSS过渡和动画是用于为网页元素添加动态效果的两种重要技术
608 143
|
7月前
|
自然语言处理 前端开发 JavaScript
用 通义灵码 一键生成“水波纹按钮”,连 CSS 动画都不用自己写了!
通义灵码是一款智能编程辅助工具,它可以根据自然语言指令自动生成高质量的代码。例如,只需输入“生成一个按钮,点击时带水波纹动画,模拟 Material Ripple 效果”,它就能生成具备完整交互逻辑、CSS 动画和良好性能的按钮组件。不仅如此,它还支持拓展功能,如长按触发提示、添加图标等,并能自动优化样式适配不同场景。通过通义灵码,开发者可以大幅提升效率,专注于创意实现,而不必纠结于繁琐的代码细节。
|
4月前
|
前端开发 算法 Java
【CSS】前端三大件之一,如何学好?从基本用法开始吧!(九):强势分析Animation动画各类参数;从播放时间、播放方式、播放次数、播放方向、播放状态等多个方面,完全了解CSS3 Animation
Animation属性 css3为Animation动画提供的几个属性如下: 属性名 属性值 animation-name 指定动画名称,该属性指定一个已有的关键帧定义。 animation-duration 指定动画持续时间。 animation-timing-funtion 指定动画变化速度。 animation-delay 指定动画延迟多长时间才开始执行。 animation-iteration-count 指定动画的循环执行次数。 animation:这是一个复合属性。
365 2
css3 svg制作404页面动画效果HTML源码
css3 svg制作404页面动画效果HTML源码
271 34
|
8月前
|
存储 自然语言处理 前端开发
抖音快手小红书虚拟评论截图生成器,模拟对话制作工具,html+js+css
这是一款纯前端实现的多平台虚拟评论生成器,支持抖音、快手、小红书风格,适用于产品演示与UI设计。采用Vanilla JS与Flexbox布局,利用IndexedDB存储数据,CSS Variables切换主题。
|
8月前
|
存储 前端开发 安全
病历单生成器在线制作,病历单生成器app,HTML+CSS+JS恶搞工具
本项目为医疗病历模拟生成器,旨在为医学教学和软件开发测试提供数据支持,严格遵守《医疗机构病历管理规定》。
|
8月前
|
存储 前端开发 JavaScript
仿真银行app下载安装, 银行卡虚拟余额制作app,用html+css+js实现逼真娱乐工具
这是一个简单的银行账户模拟器项目,用于学习前端开发基础。用户可进行存款、取款操作,所有数据存储于浏览器内存中
|
8月前
|
前端开发 容器
处方单图片生成器, 处方单在线制作免费,js+css+html恶搞神器
这是一个电子处方模拟生成系统,使用html2canvas库实现图片导出功能。系统生成的处方单包含多重防伪标识,并明确标注为模拟数据,仅供学习
|
8月前
|
前端开发 JavaScript 容器
制作b超单生成器, 假怀孕b超单图片制作, p图医院证明【css+html+js装逼恶搞神器】
本资源提供一个适合用于熟人之间恶搞的工具,效果逼真,仅供学习参考与娱乐。包含前端技术学习要点:语义化布局、响应式设计、Flexbox、图片自适应