You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何自定义CSS呼吸节奏器的吸气、屏息、呼气各阶段时长?

自定义呼吸节奏器的时长控制方案

原代码通过alternate infinite实现吸气/呼气的交替循环,但无法控制中间的屏息时长。要实现吸气→吸气后屏息→呼气→呼气后屏息的完整可控周期,需要重构动画关键帧,将整个呼吸循环拆分为四个阶段,并通过CSS变量统一管理各阶段时长。

实现思路

  1. 用CSS变量定义各阶段时长,方便快速调整
  2. 计算总周期时长,将各阶段时长转换为关键帧的百分比位置
  3. 重写所有动画的关键帧,在对应百分比位置定义状态:吸气阶段放大/位移,屏息阶段保持状态,呼气阶段缩小/复位,呼气后屏息保持最小状态

修改后的完整代码

CSS部分

/* 定义各阶段时长,直接修改这里即可调整节奏 */
:root {
  --inhale: 4s;          /* 吸气时长 */
  --hold-after-inhale: 2s; /* 吸气后屏息时长 */
  --exhale: 6s;          /* 呼气时长 */
  --hold-after-exhale: 2s; /* 呼气后屏息时长 */
  --total-duration: calc(var(--inhale) + var(--hold-after-inhale) + var(--exhale) + var(--hold-after-exhale));
}

body {
  background: #000;
  display: flex;
  align-items: center;
  height: 100vh;
  justify-content: center;
}

.watch-face {
  height: 125px;
  width: 125px;
  /* 使用总周期时长,循环播放 */
  animation: pulse var(--total-duration) cubic-bezier(0.5, 0, 0.5, 1) infinite;
}

.circle {
  height: 125px;
  width: 125px;
  border-radius: 50%;
  position: absolute;
  mix-blend-mode: screen;
  transform: translate(0, 0);
}

.circle:nth-child(odd) {
  background: #61bea2;
}

.circle:nth-child(even) {
  background: #529ca0;
}

/* 所有circle动画统一使用总周期 */
.circle:nth-child(1) {
  animation: circle-1 var(--total-duration) ease infinite;
}

.circle:nth-child(2) {
  animation: circle-2 var(--total-duration) ease infinite;
}

.circle:nth-child(3) {
  animation: circle-3 var(--total-duration) ease infinite;
}

.circle:nth-child(4) {
  animation: circle-4 var(--total-duration) ease infinite;
}

.circle:nth-child(5) {
  animation: circle-5 var(--total-duration) ease infinite;
}

.circle:nth-child(6) {
  animation: circle-6 var(--total-duration) ease infinite;
}

/* 重写pulse关键帧,包含四个阶段 */
@keyframes pulse {
  /* 初始状态:呼气后屏息的最小状态 */
  0%, calc((var(--inhale) + var(--hold-after-inhale) + var(--exhale))/var(--total-duration)*100%) {
    transform: scale(.15) rotate(180deg);
  }
  /* 吸气结束:达到最大状态 */
  calc(var(--inhale)/var(--total-duration)*100%) {
    transform: scale(1);
  }
  /* 吸气后屏息阶段:保持最大状态 */
  calc((var(--inhale) + var(--hold-after-inhale))/var(--total-duration)*100%) {
    transform: scale(1);
  }
  /* 呼气阶段:从最大回到最小 */
  calc((var(--inhale) + var(--hold-after-inhale) + var(--exhale))/var(--total-duration)*100%) {
    transform: scale(.15) rotate(180deg);
  }
  /* 呼气后屏息阶段:保持最小状态,回到初始 */
  100% {
    transform: scale(.15) rotate(180deg);
  }
}

/* 重写circle动画,同步四个阶段的位移 */
@keyframes circle-1 {
  0%, calc((var(--inhale) + var(--hold-after-inhale) + var(--exhale))/var(--total-duration)*100%) {
    transform: translate(0, 0);
  }
  calc(var(--inhale)/var(--total-duration)*100%) {
    transform: translate(-35px, -50px);
  }
  calc((var(--inhale) + var(--hold-after-inhale))/var(--total-duration)*100%) {
    transform: translate(-35px, -50px);
  }
  calc((var(--inhale) + var(--hold-after-inhale) + var(--exhale))/var(--total-duration)*100%) {
    transform: translate(0, 0);
  }
  100% {
    transform: translate(0, 0);
  }
}

@keyframes circle-2 {
  0%, calc((var(--inhale) + var(--hold-after-inhale) + var(--exhale))/var(--total-duration)*100%) {
    transform: translate(0, 0);
  }
  calc(var(--inhale)/var(--total-duration)*100%) {
    transform: translate(35px, 50px);
  }
  calc((var(--inhale) + var(--hold-after-inhale))/var(--total-duration)*100%) {
    transform: translate(35px, 50px);
  }
  calc((var(--inhale) + var(--hold-after-inhale) + var(--exhale))/var(--total-duration)*100%) {
    transform: translate(0, 0);
  }
  100% {
    transform: translate(0, 0);
  }
}

@keyframes circle-3 {
  0%, calc((var(--inhale) + var(--hold-after-inhale) + var(--exhale))/var(--total-duration)*100%) {
    transform: translate(0, 0);
  }
  calc(var(--inhale)/var(--total-duration)*100%) {
    transform: translate(-60px, 0);
  }
  calc((var(--inhale) + var(--hold-after-inhale))/var(--total-duration)*100%) {
    transform: translate(-60px, 0);
  }
  calc((var(--inhale) + var(--hold-after-inhale) + var(--exhale))/var(--total-duration)*100%) {
    transform: translate(0, 0);
  }
  100% {
    transform: translate(0, 0);
  }
}

@keyframes circle-4 {
  0%, calc((var(--inhale) + var(--hold-after-inhale) + var(--exhale))/var(--total-duration)*100%) {
    transform: translate(0, 0);
  }
  calc(var(--inhale)/var(--total-duration)*100%) {
    transform: translate(60px, 0);
  }
  calc((var(--inhale) + var(--hold-after-inhale))/var(--total-duration)*100%) {
    transform: translate(60px, 0);
  }
  calc((var(--inhale) + var(--hold-after-inhale) + var(--exhale))/var(--total-duration)*100%) {
    transform: translate(0, 0);
  }
  100% {
    transform: translate(0, 0);
  }
}

@keyframes circle-5 {
  0%, calc((var(--inhale) + var(--hold-after-inhale) + var(--exhale))/var(--total-duration)*100%) {
    transform: translate(0, 0);
  }
  calc(var(--inhale)/var(--total-duration)*100%) {
    transform: translate(-35px, 50px);
  }
  calc((var(--inhale) + var(--hold-after-inhale))/var(--total-duration)*100%) {
    transform: translate(-35px, 50px);
  }
  calc((var(--inhale) + var(--hold-after-inhale) + var(--exhale))/var(--total-duration)*100%) {
    transform: translate(0, 0);
  }
  100% {
    transform: translate(0, 0);
  }
}

@keyframes circle-6 {
  0%, calc((var(--inhale) + var(--hold-after-inhale) + var(--exhale))/var(--total-duration)*100%) {
    transform: translate(0, 0);
  }
  calc(var(--inhale)/var(--total-duration)*100%) {
    transform: translate(35px, -50px);
  }
  calc((var(--inhale) + var(--hold-after-inhale))/var(--total-duration)*100%) {
    transform: translate(35px, -50px);
  }
  calc((var(--inhale) + var(--hold-after-inhale) + var(--exhale))/var(--total-duration)*100%) {
    transform: translate(0, 0);
  }
  100% {
    transform: translate(0, 0);
  }
}

HTML部分

<div class="watch-face">
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
  <div class="circle"></div>
</div>

使用说明

直接修改:root中的四个变量值,即可分别控制各阶段时长:

  • --inhale:吸气时长
  • --hold-after-inhale:吸气后屏息时长
  • --exhale:呼气时长
  • --hold-after-exhale:呼气后屏息时长

所有动画会自动同步总周期,保持呼吸节奏的一致性。

内容的提问来源于stack exchange,提问作者gal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 20:18:08