CSS动画实战:从零打造一个超萌的小球亲亲动画

前言

最近在整理CSS动画相关的代码时,发现了一个特别有趣的小项目------两个小球的亲亲动画。这个看似简单的动画其实涉及了CSS动画的很多核心概念:border-radiusanimation、定位布局等。今天就来详细解析一下这个萌萌的动画是如何实现的。

先来看看最终效果:两个可爱的小球,左边的球会先蹭蹭右边的球,然后右边的球会主动亲一下左边的球,最后还会冒出一个小爱心。整个动画循环播放,非常治愈。

HTML结构设计

首先,我们需要设计HTML结构。这里使用了emmet语法来快速生成代码:

html 复制代码
<div class="container">
    <div id="l-ball" class="ball">
      <div class="face face-l">
        <div class="eye eye-l"></div>
        <div class="eye eye-r"></div>
        <div class="mouth"></div>
      </div>
    </div>
    <div id="r-ball" class="ball">
      <div class="face face-r">
        <div class="eye eye-l eye-r-p"></div>
        <div class="eye eye-r eye-r-p"></div>
        <div class="mouth"></div>
      </div>
    </div>
    <div class="heart"></div>
</div>

结构解析:

  • .container:页面居中的容器
  • #l-ball#r-ball:左右两个小球(id唯一标识)
  • .ball:球的通用样式(class可复用)
  • .face:小球的脸部区域
  • .eye:眼睛(每个球有两只眼睛)
  • .mouth:嘴巴
  • .heart:爱心特效

这里体现了面向对象的CSS思想,通过多类名实现样式的复用和多态。

CSS基础样式

页面布局与居中

css 复制代码
body {
    background-color: #pink;
    margin: 0;
}

.container {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 238px;
    transform: translate(-50%, -50%);
}

这里使用了经典的水平垂直居中 方案:position: absolute + transform: translate(-50%, -50%)

小球基础样式

css 复制代码
.ball {
    width: 100px;
    height: 100px;
    border: 8px solid #110202e7;
    border-radius: 50%;
    display: inline-block;
    background-color: #fff;
    vertical-align: top;
    position: relative;
}

关键技术点:

  • border-radius: 50%:将方形变成圆形
  • display: inline-block:行内块级元素,可以设置宽高且在一行显示
  • position: relative:相对定位,为子元素提供定位参考

脸部特征设计

css 复制代码
.face {
    width: 70px;
    height: 30px;
    position: absolute;
    right: 0;
    top: 30px;
    border-top-right-radius: 15px;
}

.eye {
    width: 15px;
    height: 14px;
    border-radius: 50%;
    border-bottom: 5px solid #020000;
    position: absolute;
}

.mouth {
    width: 30px;
    height: 14px;
    border-radius: 50%;
    border-bottom: 5px solid #020000;
    position: absolute;
    bottom: -5px;
    left: 0;
    right: 0;
    margin: auto;
}

这里使用了绝对定位position: absolute),子元素会相对于最近的position不为static的父元素进行定位。

动画世界的精彩

左球的蹭蹭动画

css 复制代码
#l-ball {
    animation: nuzzleLeft 4s ease-in-out infinite;
    z-index: 2;
}

@keyframes nuzzleLeft {
    0%, 100% { transform: translateX(0) rotate(0deg); }
    
    /* 第一次蹭 */
    10% { transform: translateX(20px) rotate(-5deg); }
    15% { transform: translateX(20px) rotate(5deg); }
    20% { transform: translateX(20px) rotate(-5deg); }
    25% { transform: translateX(0) rotate(0deg); }
    
    /* 第二次蹭 */
    35% { transform: translateX(20px) rotate(-5deg); }
    40% { transform: translateX(20px) rotate(5deg); }
    45% { transform: translateX(20px) rotate(-5deg); }
    50% { transform: translateX(0) rotate(0deg); }
    
    /* 保持静止,等右球亲它 */
    55%, 80% { transform: translateX(0) rotate(0deg); }
}

右球的亲亲动画

css 复制代码
#r-ball {
    animation: kissRight 4s ease-in-out infinite;
    z-index: 1;
}

@keyframes kissRight {
    /* 初始静止,等左球蹭完 */
    0%, 55% { transform: translateX(0) rotate(0deg); }
    
    /* 向左亲 */
    65% { transform: translateX(-30px) rotate(5deg); }
    70% { transform: translateX(-30px) scale(0.9) rotate(5deg); }
    75% { transform: translateX(-30px) rotate(5deg); }
    
    /* 回到初始位置 */
    80%, 100% { transform: translateX(0) rotate(0deg); }
}

爱心特效

css 复制代码
.heart {
    position: absolute;
    top: 10px;
    left: 50%;
    transform: translateX(-50%);
    width: 30px;
    height: 30px;
    background-color: #ff3366;
    animation: heartBeat 4s ease-in-out infinite;
    opacity: 0;
    clip-path: path('M15,8 C15,8 14,3 9,3 C4,3 3,8 3,8 C3,8 3,13 15,20 C27,13 27,8 27,8 C27,8 26,3 21,3 C16,3 15,8 15,8 Z');
    z-index: 10;
}

@keyframes heartBeat {
    0%, 64%, 100% { transform: translateX(-50%) scale(0); opacity: 0; }
    70% { transform: translateX(-50%) scale(1.2); opacity: 1; }
    73% { transform: translateX(-50%) scale(1); opacity: 1; }
    76% { transform: translateX(-50%) scale(1.1); opacity: 1; }
    80% { transform: translateX(-50%) scale(0); opacity: 0; }
}

这里使用了clip-path来绘制爱心形状,搭配缩放动画实现心跳效果。

细节优化:嘴巴表情动画

为了让动画更加生动,我们还给小球的嘴巴添加了表情变化:

css 复制代码
@keyframes leftMouth {
    0%, 100% { width: 30px; border-bottom-width: 5px; }
    /* 蹭的时候嘴巴微微变化 */
    10%, 20%, 35%, 45% { width: 25px; border-bottom-width: 6px; }
    15%, 40% { width: 28px; border-bottom-width: 5px; }
    /* 被亲的时候嘴巴变化 */
    65%, 75% { width: 15px; border-bottom-width: 7px; }
}

@keyframes rightMouth {
    0%, 60%, 100% { width: 30px; border-bottom-width: 5px; }
    /* 亲的时候嘴巴变化 */
    65%, 75% { width: 15px; border-bottom-width: 7px; }
}

核心知识点总结

1. Display属性的妙用

  • div默认是block(块级),独占一行
  • spania等是inline(行内),不能设置宽高
  • inline-block(行内块级):既能设置宽高,又能在一行显示

2. 定位系统

  • position: relative:相对定位,子元素相对它定位,同时相对于自身位置定位
  • position: absolute:绝对定位,会找到离它最近的position不为static的父元素进行定位,直到body为止

3. 面向对象的CSS

通过多类名实现样式的复用和多态,比如.ball类可以被多个元素使用,而#l-ball#r-ball的id则用于区分不同的动画效果。

实际应用场景

这个动画虽然看起来简单,但包含了很多实用的技术:

  1. 加载动画:可以改造成各种加载提示
  2. 交互反馈:点赞、收藏等操作的动画效果
  3. 情感化设计:增加产品的趣味性和用户粘性
  4. 节日主题:情人节、七夕等节日氛围营造

结语

通过这个小球亲亲动画,我们学习了CSS动画的核心概念:关键帧动画、定位布局、样式复用等。虽然是一个简单的动画,但其中蕴含的CSS技巧却很实用。

CSS动画的魅力就在于此------用简单的代码创造出生动有趣的效果。在实际项目中,这些技巧可以大大提升用户体验,让冰冷的界面变得温暖有趣。

相关推荐
绅士玖6 分钟前
📝 深入浅出 JavaScript 拷贝:从浅拷贝到深拷贝 🚀
前端
中微子16 分钟前
闭包面试宝典:高频考点与实战解析
前端·javascript
brzhang16 分钟前
前端死在了 Python 朋友的嘴里?他用 Python 写了个交互式数据看板,着实秀了我一把,没碰一行 JavaScript
前端·后端·架构
G等你下课44 分钟前
告别刷新就丢数据!localStorage 全面指南
前端·javascript
该用户已不存在1 小时前
不知道这些工具,难怪的你的Python开发那么慢丨Python 开发必备的6大工具
前端·后端·python
爱编程的喵1 小时前
JavaScript闭包实战:从类封装到防抖函数的深度解析
前端·javascript
LovelyAqaurius1 小时前
Unity URP管线着色器库攻略part1
前端
Xy9101 小时前
开发者视角:App Trace 一键拉起(Deep Linking)技术详解
java·前端·后端
lalalalalalalala1 小时前
开箱即用的 Vue3 无限平滑滚动组件
前端·vue.js
前端Hardy1 小时前
8个你必须掌握的「Vue」实用技巧
前端·javascript·vue.js