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

相关推荐
知了清语11 分钟前
pnpm之monorepo项目, vite版本冲突, 导致vite.config.ts ts警告处理
前端
弗锐土豆34 分钟前
一个基于若依(ruoyi-vue3)的小项目部署记录
前端·vue.js·部署·springcloud·ruoyi·若依
Hilaku36 分钟前
我为什么放弃了“大厂梦”,去了一家“小公司”?
前端·javascript·面试
1undefined238 分钟前
element中的table改造成虚拟列表(不定高),并封装成hooks
前端·vue.js
浅墨momo42 分钟前
搭建第一个Shopify App
前端·程序员
然我1 小时前
React 事件机制:从代码到原理,彻底搞懂合成事件的核心逻辑
前端·react.js·面试
Codebee1 小时前
OneCode 组件服务通用协议栈:构建企业级低代码平台的技术基石
前端·前端框架·开源
Running_C1 小时前
常见web攻击类型
前端·http
jackyChan1 小时前
ES6 Proxy 性能问题,你真知道吗?🚨
前端·javascript