css中animation与js的绑定原来还能这样玩。。。

先说使用的2个animation关键属性♥️

animation-delay:指定从应用动画到元素开始执行动画之前等待的时间量。动画可以稍后开始、立即从开头开始或立即开始并在动画中途播放。

animation-play-state:属性设置动画是运行还是暂停。

先创建一个简单的动画场景,效果如下

就是一个哭脸到笑脸的变化animation动画

代码

js 复制代码
<template>
  <div class="content">
    <div class="outer_box"></div>
    <div class="face">
      <div class="eye_left"></div>
      <div class="eye_right"></div>
      <div class="mouse"></div>
    </div>
  </div>
</template>
<style lang="scss" scoped>
.wrap {
  padding: 30px;
}

.content {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  .face {
    width: 100px;
    height: 100px;
    background: #d52f31;
    border-radius: 50%;
    position: relative;
  }
  .eye_left,
  .eye_right {
    width: 20px;
    position: absolute;
    top: 30px;
    height: 20px;
    background: #fff;
    border-radius: 50%;
  }
  .face {
    animation: changeFace 1s linear alternate-reverse infinite;
    animation-delay: v-bind(delay);
  }
  .eye_left {
    left: 20px;
    animation: changeEyeLeft 1s linear alternate-reverse infinite;
    clip-path: polygon(0 54%, 100% 0, 100% 100%, 0% 100%);
    animation-delay: v-bind(delay);
  }
  .eye_right {
    right: 20px;
    animation: changeEyeRight 1s linear alternate-reverse infinite;
    clip-path: polygon(0 0, 100% 54%, 100% 100%, 0% 100%);
    animation-delay: v-bind(delay);
  }
  .mouse {
    position: absolute;
    bottom: 20px;
    left: 50%;
    width: 50px;
    height: 10px;
    border-radius: 50%;
    margin-left: -25px;
    background: #fff;
    animation: changeMouse 1s linear alternate-reverse infinite;
    animation-delay: v-bind(delay);
  }
}
@keyframes changeFace {
  0% {
    background: #d52f31;
  }
  50% {
    background: #ffcc33;
  }
  100% {
    background: #26b66a;
  }
}
@keyframes changeMouse {
  50% {
    height: 4px;
    box-shadow: inset 0 4px 0 #fff;
    transform: translateY(10px);
    clip-path: inset(10% 0% 0% 0%);
  }
  50.1% {
    height: 4px;
    box-shadow: inset 0 -4px 0 #fff;
    transform: translateY(10px);
    clip-path: inset(50% 0% 0% 0%);
  }
  to {
    height: 40px;
    box-shadow: inset 0 -50px 0 #fff;
    transform: translateY(10px);
    clip-path: inset(50% 0% 0% 0%);
  }
}
@keyframes changeEyeLeft {
  0% {
    clip-path: polygon(0 54%, 100% 0, 100% 100%, 0% 100%);
  }
  100% {
    clip-path: polygon(0 0, 100% 0, 100% 100%, 0% 100%);
  }
}
@keyframes changeEyeRight {
  0% {
    clip-path: polygon(0 0, 100% 54%, 100% 100%, 0% 100%);
  }
  100% {
    clip-path: polygon(0 0, 100% 0, 100% 100%, 0% 100%);
  }
}
</style>

使用js绑定并控制动画进度⚡

将animation-play-state设置为pause使动画暂停住

js 复制代码
...
  .face {
    animation: changeFace 1s linear forwards paused;
  }
  .eye_left {
    left: 20px;
    animation: changeEyeLeft 1s linear forwards paused;
    clip-path: polygon(0 54%, 100% 0, 100% 100%, 0% 100%);
  }
  .eye_right {
    right: 20px;
    animation: changeEyeRight 1s linear forwards paused;
    clip-path: polygon(0 0, 100% 54%, 100% 100%, 0% 100%);
  }
...

这里我们加一个input并且类型为range的滑动条来控制

js 复制代码
<template>
  <div class="content">
    <div class="outer_box"></div>
    <div class="face">
      <div class="eye_left"></div>
      <div class="eye_right"></div>
      <div class="mouse"></div>
    </div>
    <input
      type="range"
      style="margin-top: 20px"
      min="0"
      :step="0.01"
      max="1"
      @input="changeInput"
    />
  </div>
</template>

这里我们需要控制动画在1s内的变化,所以设置min0max1,然后变化的step0.01,这样input的事件拿到的value值范围就是从0-1的值

然后设置一个统一的delay,它的值是由-e.target.value决定,然后将它应用到animation里就能控制动画了

js 复制代码
<script lang="ts" setup>
import { ref } from "vue";
const delay = ref("");
const changeInput = (e) => {
  delay.value = -e.target.value + "s";
};
</script>
<style>
...
 .face {
    animation: changeFace 1s  linear forwards paused;
    animation-delay: v-bind(delay);
  }
  .eye_left {
    left: 20px;
    animation: changeEyeLeft 1s linear forwards paused;
    clip-path: polygon(0 54%, 100% 0, 100% 100%, 0% 100%);
    animation-delay: v-bind(delay);
  }
  .eye_right {
    right: 20px;
    animation: changeEyeRight 1s linear forwards paused;
    clip-path: polygon(0 0, 100% 54%, 100% 100%, 0% 100%);
    animation-delay: v-bind(delay);
  }
  ...
</style>

效果✨

全部代码

js 复制代码
<template>
  <div class="content">
    <div class="outer_box"></div>
    <div class="face">
      <div class="eye_left"></div>
      <div class="eye_right"></div>
      <div class="mouse"></div>
    </div>
    <input
      type="range"
      style="margin-top: 20px"
      min="0"
      :step="0.01"
      max="1"
      @input="changeInput"
    />
  </div>
</template>
<script lang="ts" setup>
import { ref } from "vue";
const delay = ref("");
const changeInput = (e) => {
  console.log(e.target.value);
  delay.value = -e.target.value + "s";
};
</script>
<style lang="scss" scoped>
.wrap {
  padding: 30px;
}

.content {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  .face {
    width: 100px;
    height: 100px;
    background: #d52f31;
    border-radius: 50%;
    position: relative;
  }
  .eye_left,
  .eye_right {
    width: 20px;
    position: absolute;
    top: 30px;
    height: 20px;
    background: #fff;
    border-radius: 50%;
  }
  .face {
    animation: changeFace 1s linear forwards paused;
    animation-delay: v-bind(delay);
  }
  .eye_left {
    left: 20px;
    animation: changeEyeLeft 1s linear forwards paused;
    clip-path: polygon(0 54%, 100% 0, 100% 100%, 0% 100%);
    animation-delay: v-bind(delay);
  }
  .eye_right {
    right: 20px;
    animation: changeEyeRight 1s linear forwards paused;
    clip-path: polygon(0 0, 100% 54%, 100% 100%, 0% 100%);
    animation-delay: v-bind(delay);
  }
  .mouse {
    position: absolute;
    bottom: 20px;
    left: 50%;
    width: 50px;
    height: 10px;
    border-radius: 50%;
    margin-left: -25px;
    background: #fff;
    animation: changeMouse 1s linear forwards paused;
    animation-delay: v-bind(delay);
  }
}
@keyframes changeFace {
  0% {
    background: #d52f31;
  }
  50% {
    background: #ffcc33;
  }
  100% {
    background: #26b66a;
  }
}
@keyframes changeMouse {
  50% {
    height: 4px;
    box-shadow: inset 0 4px 0 #fff;
    transform: translateY(10px);
    clip-path: inset(10% 0% 0% 0%);
  }
  50.1% {
    height: 4px;
    box-shadow: inset 0 -4px 0 #fff;
    transform: translateY(10px);
    clip-path: inset(50% 0% 0% 0%);
  }
  to {
    height: 40px;
    box-shadow: inset 0 -50px 0 #fff;
    transform: translateY(10px);
    clip-path: inset(50% 0% 0% 0%);
  }
}
@keyframes changeEyeLeft {
  0% {
    clip-path: polygon(0 54%, 100% 0, 100% 100%, 0% 100%);
  }
  100% {
    clip-path: polygon(0 0, 100% 0, 100% 100%, 0% 100%);
  }
}
@keyframes changeEyeRight {
  0% {
    clip-path: polygon(0 0, 100% 54%, 100% 100%, 0% 100%);
  }
  100% {
    clip-path: polygon(0 0, 100% 0, 100% 100%, 0% 100%);
  }
}
</style>

完结❤️

相关推荐
KaMeidebaby6 小时前
卡梅德生物技术快报|蛋白 N 端测序在重组贻贝融合蛋白表征中的应用,解决原核表达序列偏移工艺难题
前端·人工智能·物联网·算法·百度
kyriewen7 小时前
我筛了 1400 个 Claude Code Skills,留下 5 个天天在用的
前端·ai编程·claude
JNX_SEMI7 小时前
AT2401C 2.4GHz 全集成射频前端单芯片技术解析
前端·单片机·嵌入式硬件·物联网·硬件工程
anOnion8 小时前
Agentic 前端开发之 实时显示 AI Agent 终端输出
前端·javascript·人工智能
随风一样自由8 小时前
【前端领域】2026最新前端领域全梳理(框架/工具/AI/跨端/底层标准/就业趋势)
前端·人工智能·前端框架
这是个栗子8 小时前
【前端性能优化】优化数据加载:用 Promise.all 从串行到并行
前端·javascript·性能优化·异步编程·前端优化·promise.all
fei_sun8 小时前
黑洞路由(Null Route/空接口路由)
服务器·前端·javascript
大爱一家盟9 小时前
告别卡点BGM同质化 2026原创卡点音乐素材下载网站 TOP5 推荐
大数据·前端·人工智能
彦为君9 小时前
算法思维与经典智力题
java·前端·redis·算法
aa小小9 小时前
localhost 访问异常排查笔记
前端