如何使用 CSS 创建动画 SVG 脸
了解如何使用 CSS 动画、变换和可选的 JavaScript 创建动画 SVG 脸。
这是我的网络应用程序ButtonBuddy.dev中使用的动画的独立演示,您可以在其中了解可访问的按钮对比度,然后生成您自己的可访问按钮调色板。
以下是允许您改变 Buddy 情绪的演示预览:
创建 SVG 脸部
我们可以使用两个 SVG 元素来实现基本脸部:
- 两只
ellipse
眼睛 - 一个
path
用于嘴巴
但首先我们需要我们的基本 SVG 元素,我们将为其包含一个viewBox
属性,该属性充当 SVG 的窗口并提供 SVG 宽高比的提示:
<svg viewBox="0 0 100 60"></svg>
接下来,我们来添加眼睛。除了属性之外,它们几乎完全相同,该属性会沿着cx
的位置移动。ellipse
x-axis
<svg viewBox="0 0 100 60">
<ellipse cx="15" cy="12" rx="8" ry="9" class="eye right-eye" fill="currentColor" />
<ellipse cx="80" cy="12" rx="8" ry="9" class="eye left-eye" fill="currentColor" />
</svg>
我们添加fill="currentColor"
以便颜色默认为 SVG 最接近祖先的文本颜色。
您可以查看MDN 文档ellipse
以获取有关其他属性的更多信息。
最后,我们添加一个path
来表示微笑:
<svg viewBox="0 0 100 60">
<!-- (ellipses) -->
<path
stroke-linecap="round"
d="M30 40 c0 20, 40 20, 40 0"
fill="currentColor" stroke="currentColor" />
</svg>
让我们分解一下属性:
stroke-linecap="round"
- 这会将路径描边的默认“端点”从方形改为更柔和的端点。这在“高兴”和“悲伤”情绪中表现得最为明显。fill
并且stroke
——我们再次使用currentColor
as describe 来表示ellipse
s。用它来fill
创建张嘴微笑的外观,以表示我们默认的情绪“兴奋”。d
- 这就是绘制路径的内容。M30 40
将起点(笑脸左侧的点)分别定位到30
x 轴上的 位置 和40
y 轴上的 位置 。这相对于我们的viewBox
。c
接下来,我们通过创建对来创建一条曲线x y
。每两个数字组成一对,因此0 20
意味着0x 20y
。这些值与 相对M
,并为 SVG 创建控制点,以便按照 MDN 文档 中的说明绘制贝塞尔曲线。
这是带有贝塞尔曲线控制点的面:
塑造情感
我们的第一个情绪“兴奋”是如上所述的默认状态。
对于“高兴”和“悲伤”表情,我们希望移除fill
,path
将嘴部外观改为闭嘴微笑。我们还将增加stroke-width
:
svg.happy path,
svg.sad path {
fill: transparent;
stroke-width: 6px;
}
完整的演示展示了如何使用clamp
更加动态的大小stroke-width
和按钮font-size
。
对于悲伤,我们需要将笑脸翻转过来,我们可以通过 CSS 变换快速实现这一点:
svg.sad path {
transform: scaleY(-1);
transform-origin: 50% 80%;
}
水平翻转元素。由于scaleY(-1)
SVG 中有多个元素,我们还必须使用transform-origin
来确保 的变换path
是相对于其原始位置的。说实话,找到这些值需要一些反复试验 :)
在演示中,您还会看到添加了过渡效果,以便从一种情绪平滑过渡到另一种情绪。总而言之,这些属性可以实现简单而有效的动画,而无需引入动画框架。
眨眼动画
眨眼transform
动画也使用了 中的“但是” @keyframes
。我们交替使用“眯眼”(通过压平眼睛来实现ellipse
)和完全睁开来产生眨眼效果:
@keyframes wink {
0%,
20%,
70% {
transform: scale(1.5, 0.25);
}
30%,
50%,
90%,
100% {
transform: scale(1);
}
}
斜视使用了一种类似于球体挤压的经典动画技巧,在函数中,它同时略微加宽元素( 1.5
)并减小其高度( ) 。这些数字是计算出的元素大小的比例。因此,为了使其恢复到原始大小,我们将两者的值都更新为(由于两者的值相同,因此我们可以用一个数字来定义)。0.25
scale
1
要应用wink
动画,请使用以下 CSS 规则:
svg.wink .eye:last-of-type {
/* Ensure the default element is at normal scale */
transform: scale(1);
transform-origin: 90% 20%;
animation: wink 480ms ease-in-out 1;
}
再次,我们必须transform-origin
根据与微笑相同的理由进行调整path
。
480ms
我们应用了持续时间为、缓动函数为 的动画ease-in-out
,并播放了1
一次。
但是你可能在开头的预览 gif 中注意到了(或者如果你直接跳到演示版),眨眼动画会时不时地重复出现。为此,我们需要添加一些 JavaScript 代码来重新触发动画。
最小的 Javascript 找到 SVG 元素,然后每毫秒(5 秒)setInterval
添加一次类。wink
5000
重要的是,我们添加了一个事件监听器来animationend
移除该类。wink
添加和移除该类wink
允许按间隔重新启动动画。
const buddy = document.querySelector(".buddy svg");
setInterval(() => {
buddy.classList.add("wink");
}, 5000);
// Remove the wink class to reset the animation after it ends
buddy.addEventListener("animationend", () => {
buddy.classList.remove("wink");
});
该演示包括一个额外的检查,仅wink
当 Buddy 不“悲伤”时才允许添加该类。
演示
您可以在此 CodePen 中查看完整的演示,然后查看ButtonBuddy.dev来创建您自己的可访问按钮调色板!
鏂囩珷鏉ユ簮锛�https://dev.to/5t3ph/how-to-create-an-animated-svg-face-with-css-5djd如果您喜欢本教程和ButtonBuddy,请查看我在ModernCSS.dev上的其他 CSS 资源,并考虑请我喝杯咖啡。