css 音频动画
CSS and HTML have opened a rich playing field for adding multimedia content to your web page, web app, and e-book projects. One innovative way of combining these two technologies is adding sound effects to your CSS animations using elements and triggering them with a little bit of JavaScript.
CSS和HTML为在您的网页,Web应用程序和电子书项目中添加多媒体内容开辟了一个广阔的竞争环境。 结合这两种技术的一种创新方法是使用元素在CSS动画中添加声音效果,并使用少量JavaScript触发它们。
Although sound on the web isn’t universally welcome, there are cases when it can enrich the user experience without being an unnecessary annoyance. Examples are artist and gaming websites or content for children. Sound can even be useful in certain cases to visitors with disabilities.
尽管不普遍欢迎网络上的声音,但在某些情况下它可以丰富用户体验而又不会造成不必要的烦恼。 例如艺术家和游戏网站或儿童内容。 在某些情况下,声音甚至对残障游客很有用。
The most important part of the sound animation process is adjusting your CSS animation to the audio to achieve an accurate in-sync audio-visual experience. In this article I’ll go through the steps of syncing animation keyframes to audio timing data using an interesting example of a beating stylized heart.
声音动画过程中最重要的部分是将CSS动画调整为音频,以获得准确的同步视听体验。 在本文中,我将使用一个有趣的跳动的程式化示例,介绍将动画关键帧同步到音频定时数据的步骤。
See the Pen CSS Animation with Sound: Heartbeat by SitePoint (@SitePoint) on CodePen.
见笔CSS动画与声音:心跳由SitePoint( @SitePoint上) CodePen 。
The first ingredient we need is a heart we want to animate. We will construct one using CSS pseudo-elements. Having it constructed in HTML rather than using an image, even if only through pseudo-elements, gives us the opportunity to animate various CSS properties to create a more interesting animation.
我们需要的第一个要素是我们要赋予生命的心。 我们将使用CSS伪元素构造一个。 即使仅通过伪元素,也可以用HTML而不是使用图像来构造它,这使我们有机会对各种CSS属性进行动画处理以创建更有趣的动画。
We can often find more than one way to build a shape this way, but if we plan to animate it it’s worth thinking about geometry and how different structural choices affect movement and simplify the keyframes code.
我们经常可以找到不止一种这样的形状来创建形状,但是如果要对其进行动画处理,则值得考虑几何形状以及不同的结构选择如何影响运动并简化关键帧代码。
In this case the simplest technique is to use two vertical rectangles rounded on top, rotated, and positioned to overlap to form a heart shape. Their size is set using percentages and they’re absolutely positioned with a bit of geometry consideration so it’s easy to scale the original shape by changing the container size. The rectangles are rotated 45 degrees clockwise and counterclockwise to form the left and right parts of the heart.
在这种情况下,最简单的技术是使用两个在顶部倒圆 ,旋转并定位为重叠以形成心形的垂直矩形。 它们的大小是使用百分比设置的,并且它们在定位时完全考虑了几何形状,因此可以很容易地通过更改容器大小来缩放原始形状。 矩形顺时针和逆时针旋转45度,形成心脏的左右部分。
.heart::before,
.heart::after {
background-color: red;
content: "";
height: 80%;
left: 25%;
position: absolute;
top: 2%;
transform: translateZ(0) rotate(-45deg);
width: 50%;
}
.heart::after {
transform: translateZ(0) rotate(45deg);
}
Rounded sides are set with two radii values to get an elliptic rather than circular curve, and therefore a more natural heart shape. Because rectangle side lengths have a 5/8 ratio, the ellipsis radii calculate to 50%/37.5% to round off only the corners that don’t overlap.
圆角的边设置有两个半径值以获得椭圆而不是圆形的曲线,因此心形更自然。 由于矩形边长的比例为5/8,因此椭圆半径计算为50%/ 37.5%,以仅舍入不重叠的角。
.heart::before,
.heart::after {
border-radius: 50% 50% 0 0 / 37.5% 37.5% 0 0;
}
Now what remains is to adjust the transform-origin point for the rectangles so the points line up at the center of the square area where the rectangles do overlap. The same look can be achieved by adjusting the absolute position declarations instead of using the transform-origin
approach. But that would later complicate the keyframes code because it would force us to control the position in more detail instead of relying on the transform
scale function to do the work for us.
现在剩下的就是调整矩形的变换原点 ,以便这些点在矩形确实重叠的正方形区域的中心对齐。 通过调整绝对位置声明而不是使用transform-origin
方法可以实现相同的外观。 但这会使关键帧代码复杂化,因为这将迫使我们更详细地控制位置,而不是依靠transform
比例函数来为我们完成工作。
The transform-origin
point should be calculated with regards to the coordinate system before any transforms are applied (because transforms can affect the coordinate system, for example, the rotate()
function rotates the coordinate system along with the element it is applied to). Again the sides length ratio dictates the position of that point: it is easy to see that the X position is at 50%, at the center of the rectangles, but the Y position is calculated at 68.75% of the rectangle height measured from the top (55*100%/80=68.75%). Going with the specific symmetry approach pays off here too, as both rectangles share the same transform-origin
point position.
在应用任何变换之前,应针对坐标系计算transform-origin
(因为变换会影响坐标系,例如, rotate()
函数将坐标系及其所应用的元素一起旋转)。 同样,边长比决定了该点的位置:很容易看到X位置在矩形的中心处为50%,但是Y位置的计算是从顶部测量的矩形高度的68.75%。 (55 * 100%/ 80 = 68.75%)。 采用特定的对称方法在这里也很有意义,因为两个矩形共享相同的transform-origin
起点位置。
.heart::before,
.heart::after {
transform-origin: 50% 68.75% 0;
}
And now we have a beautiful symmetric heart shape. We can add an inset box-shadow
, different for each rectangle, to make it all plump and 3D.
现在我们有了美丽的对称心形。 我们可以添加每个矩形都不同的inset box-shadow
,以使其全部丰满和3D。
.heart::before {
box-shadow: -8px -14px 10px 0 black inset;
}
.heart::after {
box-shadow: -15px 10px 14px 0 black inset;
}
To introduce audio into the page, we use the element with the path to the audio file and without the
controls
attribute because we don’t want the internal browser audio player to appear (read more in Using HTML5 audio and video on MDN).
要将音频引入页面中,我们将元素与音频文件的路径一起使用,并且不带
controls
属性,因为我们不希望内部浏览器音频播放器出现(请参阅在MDN上使用HTML5音频和视频中的更多内容) )。
Instead of the controls, we use JavaScript to manipulate the playback. This example uses buttons to start and reset the track, but with a little bit more work we could do without the buttons and start and reset the audio when the heart element is clicked or hovered.
代替控件,我们使用JavaScript来操纵回放。 此示例使用按钮来启动和重置轨道,但是如果不单击按钮,我们可以做更多的工作,而在单击或悬停心脏元素时,可以启动和重置音频。
Our sound is the sound of a heartbeat repeated four times and it will serve as the sound our CSS animation will follow.
我们的声音是重复四次的心跳声,它将作为CSS动画跟随的声音。
To make our heart tick, we need to change its shape from original, resting heart, to the state when the muscle is flexed. To flex the heart we scale it down a bit and change its shape with border-radius
.
为了使心脏跳动,我们需要将其形状从原始的静止心脏转变为弯曲肌肉的状态。 为了使心脏弯曲,我们将心脏按比例缩小,并通过border-radius
改变其形状。
Here is how the flexed styles would read if we needed them static, outside of the animation:
如果我们在动画之外需要静态样式,这是柔性样式的读取方式:
.heart::before,
.heart::after {
background-color: orange;
transform: rotate(-45deg) scale(0.8);
border-radius: 70% 70% 70% 0 / 70% 70% 10% 0;
}
.heart::after {
transform: rotate(-45deg) scale(0.8);
}
The transition between the resting and flexed states and then back to the original resting shape makes one heart beat. Our keyframe percentages effectively declare, in turns, the resting and flexed styles. But to make it sync with the audio we need to know exactly how long the animation should play and which keyframes percentages to use for which heart state. Some useful audio software can help us analyze the sound and note the timing information we need for our keyframes.
在静息状态和屈曲状态之间的过渡,然后回到原始的静息形状,使人心跳加快。 我们的关键帧百分比依次有效地声明了休息和灵活的样式。 但是要使其与音频同步,我们需要确切地知道动画应播放多长时间,以及在哪种心态下要使用哪些关键帧百分比。 一些有用的音频软件可以帮助我们分析声音并记录关键帧所需的定时信息。
Audacity® is open source cross-platform software for recording and editing sounds. It is easy to use and even if you don’t have experience with similar audio or video editing software it won’t take a lot of effort to get the information you need.
Audacity®是用于记录和编辑声音的开源跨平台软件。 它易于使用,即使您没有使用类似音频或视频编辑软件的经验,也不会花费很多精力来获取所需的信息。
Open your audio signal in Audacity and it will automatically show you the sound waveform. In most cases this will be enough for you to recognize where certain parts of the audio start and end, by looking at the signal shape. Rarely we get a signal where some other spectrogram view mode helps better, but in that case we can switch between different modes through the drop-down menu next to the spectrogram.
在Audacity中打开音频信号,它将自动向您显示声音波形。 在大多数情况下,这足以让您通过查看信号形状来识别音频的某些部分的开始和结束位置。 很少会收到其他频谱图查看模式更有用的信号,但在这种情况下,我们可以通过频谱图旁边的下拉菜单在不同模式之间进行切换。
Clicking on the spectrogram marks a moment on the timeline, and below it you can read in seconds what time it corresponds to. This is how we find out when each heartbeat starts, ends, and when the heart is in the flexed state. We use the play button to play the entire audio or select a segment, and note the times we need for the animation keyframes.
单击频谱图会在时间轴上标记一个时刻,在其下方您可以在几秒钟内读取对应的时间。 这是我们找出每次心跳开始,结束的时间以及心脏处于弯曲状态的方式。 我们使用播放按钮播放整个音频或选择一个片段,并注意动画关键帧所需的时间。
In our heartbeat case we have 4 distinct heartbeats and it’s easy to recognize it by looking at the waveform. We need to take note of each heartbeat, when it starts, ends, and when it’s in the flexed state. To make this easier we use a spreadsheet app where we note the heartbeats and their timing in seconds.
在我们的心跳情况下,我们有4种不同的心跳,通过查看波形很容易识别它。 我们需要记下每个心跳的开始,结束以及处于弹性状态的时间。 为了简化此过程,我们使用了电子表格应用程序,其中记录了心跳及其计时(以秒为单位)。
Once we have the timing in seconds, we use some math to normalize the audio length to the 100% length notation we use in the animation (multiply by 100 and divide by the total audio time). This is how we get the keyframes percentages as well as what style should be applied to a particular keyframe, whether the heart should be relaxed or flexed.
一旦有了以秒为单位的计时,我们就可以使用一些数学运算将音频长度标准化为动画中使用的100%长度标记(乘以100,再除以总音频时间)。 这是我们获取关键帧百分比的方式,以及如何对特定关键帧应用哪种样式,无论心脏应该放松还是弯曲。
Reading from this table we can create the keyframes percentages and fill them in with the styles associated with each. In addition to scaling the heart and the border-radius
we also change the heart color to emphasize the animation a bit more. Since we’re using transform
to scale the heart rectangles, and each rectangle also has a different rotate value, we have to create two different animations, one for each rectangle.
从该表中读取信息,我们可以创建关键帧百分比,并用与之相关的样式填充它们。 除了缩放心脏和border-radius
我们还更改了心脏颜色以更加强调动画效果。 由于我们使用transform
缩放心形矩形,并且每个矩形也具有不同的旋转值,因此我们必须创建两个不同的动画,每个矩形一个。
Here is the @keyframes
code for the left rectangle (the right rectangle animation only differs in rotation orientation values and border-radius
position):
这是左矩形的@keyframes
代码(右矩形动画仅在旋转方向值和border-radius
位置上有所不同):
@keyframes heartbeats-before {
3% {
background-color: red;
transform: rotate(-45deg) scale(1);
border-radius: 50% 50% 0 0 / 37.5% 37.5% 0 0;
}
8.2% {
background-color: orange;
transform: rotate(-45deg) scale(0.8);
border-radius: 70% 70% 70% 0 / 70% 70% 10% 0;
}
13.7% {
background-color: red;
transform: rotate(-45deg) scale(1);
border-radius: 50% 50% 0 0 / 37.5% 37.5% 0 0;
}
25% {
background-color: red;
transform: rotate(-45deg) scale(1);
border-radius: 50% 50% 0 0 / 37.5% 37.5% 0 0;
}
30% {
background-color: orange;
transform: rotate(-45deg) scale(0.8);
border-radius: 70% 70% 70% 0 / 70% 70% 10% 0;
}
36% {
background-color: red;
transform: rotate(-45deg) scale(1);
border-radius: 50% 50% 0 0 / 37.5% 37.5% 0 0;
}
44.4% {
background-color: red;
transform: rotate(-45deg) scale(1);
border-radius: 50% 50% 0 0 / 37.5% 37.5% 0 0;
}
49.6% {
background-color: orange;
transform: rotate(-45deg) scale(0.8);
border-radius: 70% 70% 70% 0 / 70% 70% 10% 0;
}
56.4% {
background-color: red;
transform: rotate(-45deg) scale(1);
border-radius: 50% 50% 0 0 / 37.5% 37.5% 0 0;
}
66.7% {
background-color: red;
transform: rotate(-45deg) scale(1);
border-radius: 50% 50% 0 0 / 37.5% 37.5% 0 0;
}
71.8% {
background-color: orange;
transform: rotate(-45deg) scale(0.8);
border-radius: 70% 70% 70% 0 / 70% 70% 10% 0;
}
77% {
background-color: red;
transform: rotate(-45deg) scale(1);
border-radius: 50% 50% 0 0 / 37.5% 37.5% 0 0;
}
}
Finally we assign the corresponding animations to the rectangles. We set the total animation length to the heartbeat audio length, set it to play only once, with a linear timing function, and with no delay. Using a timing function other than linear would mess up the syncing between the animation and the audio, so always remember to use a linear timing function when syncing to an external resource.
最后,我们将相应的动画分配给矩形。 我们将动画总长度设置为心跳音频长度,将其设置为仅播放一次,并且具有线性计时功能,并且没有延迟。 使用线性以外的计时功能会扰乱动画和音频之间的同步,因此在与外部资源同步时,请始终记住使用线性计时功能。
.heart.active::before {
animation: heartbeats-before 5.85s linear 0 1;
}
The animation is assigned to a special class we add to the heart element with JavaScript, at the same event we trigger the audio play. This is how we ensure the animation and the audio start at the same time and all the syncing work pays off.
动画被分配给一个特殊类,我们使用JavaScript将其添加到heart元素中,同时触发音频播放。 这是我们确保动画和音频同时开始并且所有同步工作都得到回报的方式。
And that’s it for the heartbeat animation, which you can see in the demo below.
这就是心跳动画的内容,您可以在下面的演示中看到它。
See the Pen CSS Animation with Sound: Heartbeat by SitePoint (@SitePoint) on CodePen.
见笔CSS动画与声音:心跳由SitePoint( @SitePoint上) CodePen 。
Hungry for more CSS goodies you can hear as well as observe? Here are some more examples you can take apart and learn from:
渴望获得更多您可以听到并观察到CSS优点? 以下是一些更多示例,您可以从中学到一些东西:
See the Pen 5a20ef9d5c68abc42320ac73639f0e39 by SitePoint (@SitePoint) on CodePen.
请参阅CodePen上 SitePoint( @SitePoint )的Pen 5a20ef9d5c68abc42320ac73639f0e39 。
See the Pen Cuckoo Clock CSS Animation with Sound by SitePoint (@SitePoint) on CodePen.
请参阅CodePen上带有 SitePoint( @SitePoint ) 声音的Pen Cuckoo Clock CSS动画 。
See the Pen qObQro by SitePoint (@SitePoint) on CodePen.
请参阅CodePen上的SitePoint( @SitePoint )的Pen qObQro 。
Below is a list of source for the media resources used in this article:
下面是本文中使用的媒体资源的来源列表:
The Heartbeat Sound (Public domain)
心跳声(公共领域)
Railroad Crossing Signal (Public domain)
铁路道口信号(公共领域)
Cuckoo Clock Sound (Public domain)
布谷鸟钟声(公共领域)
Stopwatch Image (Public domain)
秒表图像(公共领域)
Time Running Out by Iwan Gabovitch under CC-BY 3.0 License
时间的流逝被伊万Gabovitch下, CC-BY 3.0许可
I hope this article inspires you to consider using sounds in your projects where appropriate and encourages you to come up with imaginative ways to combine the visual with the audio.
我希望本文能激发您考虑在项目中适当使用声音的方法,并鼓励您想出一些富有想象力的方法,将视觉与音频结合起来。
What about you? Have you used sounds with your animations successfully before? Is there any particular case of CSS animation you’d love to see? Tell us all about it in the comments!
你呢? 您以前在动画中成功使用声音吗? 您是否希望看到CSS动画的特殊情况? 在评论中告诉我们所有相关信息!
翻译自: https://www.sitepoint.com/syncing-css-animations-with-html5-audio/
css 音频动画