Apple Music 具有“空间音频”功能,其中您耳机中的音乐方向取决于设备的位置。 很难解释它到底有多棒。 但这不是我要谈论的。
我打开了 Apple Music 应用程序,看到了一个支持空间音频的热门歌曲特色播放列表。 它的封面是一个明亮的粉色容器,里面装着一堆一个叠一个的盒子。 这些盒子一次动画一个,在容器的中心淡入,然后在缩放至容器大小的同时淡出。 像一个无限循环。

酷! 我知道我必须在 CSS 中重新创建它。 所以我做了。
它是这样工作的……
标记
我从 HTML 开始。 显然,我们需要定义一个容器,再加上我们要动画的任何数量的框。 我在容器中使用了 10 个框。
<div class="container">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<!-- etc. -->
</div>
对于 HTML,就这些了。 我们可以直接跳到 CSS!
样式容器
这里没什么花哨的。 我根据我在 Apple Music 中看到的测量了近似尺寸,恰好是 315px
× 385px
。 然后我截取了封面的屏幕截图,并将其放到我的图像编辑应用程序中以获得最浅的可能颜色,它位于容器的外部边缘。 我的颜色选择器停在了 #eb5bec
上。
.container {
background-color: #eb5bec;
height: 315px;
width: 385px;
}
在做这件事的时候,我知道我可能希望它成为一个网格容器,以便将框和任何其他元素对齐到中心。 我还认为盒子本身将从容器的中心开始,并且一个叠在一个上面,这意味着将进行一些绝对定位。 这也意味着容器应该具有相对定位以控制它们。
.container {
background-color: #eb5bec;
height: 315px;
position: relative;
width: 385px;
}
并且由于我们希望框从中心开始,我们可以使用网格来帮助实现这一点
.container {
background-color: #eb5bec;
display: grid;
height: 315px;
place-items: center;
position: relative;
width: 385px;
}
如果容器中的框向外增长,那么它们可能会扩展到容器之外。 最好隐藏任何可能的溢出。
.container {
background-color: #eb5bec;
height: 315px;
overflow: hidden;
position: relative;
width: 385px;
}
我还注意到它有一些圆角,所以让我们在添加它的时候添加进去。
.container {
background-color: #eb5bec;
border-radius: 16px;
height: 315px;
position: relative;
width: 385px;
}
到目前为止,一切都好!
样式框
我们在标记中拥有 10 个 .box
元素,我们希望它们一个叠在一个上面。 我从一些绝对定位开始,然后将它们的大小设置为 100px
方形。 然后我使用我的图像编辑应用程序做了同样的事情来找到框的最暗颜色值,它是 #471e45
。
.box {
background: #471e45;
height: 100px;
position: absolute;
width: 100px;
}
当框变大时,它们似乎会淡出。 这允许一个框透过另一个框看到,所以让我们一开始将它们设置为不透明。
.box {
background: #471e45;
height: 100px;
opacity: 0.5;
position: absolute;
width: 100px;
}
酷,酷。 我们无法看到所有叠在一起的框,但我们正在取得进展!
创建动画
准备好编写一些 @keyframe
吗? 我们将使它非常简单,从 0 到 100% 不包含任何中间步骤。 我们甚至不需要那些百分比!
@keyframes grow {
from {
/* do stuff */
}
to {
/* do stuff */
}
}
具体来说,我们希望从开始到结束发生两件事
- 框从我们的起始不透明度值
0.5
变为0
(完全透明)。 - 框向上缩放至容器边缘。
@keyframes grow {
from {
opacity: 0.5;
transform: scale(0);
}
to {
opacity: 0;
transform: scale(3.85);
}
}
我如何将框向上缩放 3.85
? 我们的框是 100px
方形,容器是 385px
高。 值 3.85
使框在完全淡出时达到 385px
,当我们到达那里时,这将使动画变得平滑线性。
说到这里……
应用动画
在我们的框上调用动画非常容易。 只需确保它以无限的方式在一条线性计时函数上移动,这样它就像 Energizer Bunny 一样,不断地前进前进前进前进……
.box {
animation: grow 10s linear infinite; /* 10s = 10 boxes */
/* etc. */
}
这给了我们想要的动画。 但是! 所有框都在同一时间移动,因此我们只看到一个巨大的框在增长。
我们必须错开那些小家伙。 不幸的是,普通 CSS 中没有循环,因此我们必须分别延迟每个框。 我们可以从设置延迟的自定义属性开始,将其设置为一秒,然后在每个实例上重新定义自定义属性。
.box {
--delay: 1s;
animation-delay: var(--delay);
/* same as before */
}
.box:nth-child(2) {
--delay: 2s;
}
.box:nth-child(3) {
--delay: 3s;
}
.box:nth-child(4) {
--delay: 4s;
}
.box:nth-child(5) {
--delay: 5s;
}
/* five more times... */
太棒了!
继续摇摆
就这些了! 我们刚刚重新创建了 Apple Music 使用的相同效果。 我们可以添加一些收尾工作,比如内容等等。 这是我的最终版本
我不太喜欢自我宣传,但不久前我确实想到了类似的东西! 所以我想如果人们喜欢这个,他们可能也会喜欢我用 WebGL 制作的类似 Apple 主题卡片:https://fjolt.com/article/apple-cards-webl-gl-javascript
哇,这些很棒!
如果您将所有延迟设置为负值,它将从完整效果开始,而不是必须等待 10 秒才能使所有内容都动画化。
我还发现,您可以仅设置主背景,并为框使用
rgba(0, 0, 0, 0.25)
,这样您就不必计算其他颜色。 我不知道它是否完全匹配,但我认为它足够接近。使用这些更新创建了我自己的版本:https://svelte.net.cn/repl/234ce30ccabc4058a1e46013b468ee89?version=3.44.2
我喜欢这个动画,想尝试只使用一个 div 来完成它。 它大部分都在那里,但肯定可以改进一些,并且可以更好地进行关键帧设置。 当我有更多时间时,我会回去清理一下。
感谢你的灵感!