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>

完结❤️

相关推荐
IT_陈寒1 小时前
Vue3性能优化实战:这5个技巧让我的应用加载速度提升了70%
前端·人工智能·后端
树上有只程序猿1 小时前
react 实现插槽slot功能
前端
stoneship2 小时前
Web项目减少资源加载失败白屏问题
前端
DaMu2 小时前
Cesium & Three.js 【移动端手游“户外大逃杀”】 还在“画页面的”前端开发小伙伴们,是时候该“在往前走一走”了!我们必须摆脱“画页面的”标签!
前端·gis
非专业程序员2 小时前
一文读懂Font文件
前端
Asort2 小时前
JavaScript 从零开始(七):函数编程入门——从定义到可重用代码的完整指南
前端·javascript
Johnny_FEer2 小时前
什么是 React 中的远程组件?
前端·react.js
真夜2 小时前
关于rngh手势与Slider组件手势与事件冲突解决问题记录
android·javascript·app
我是日安2 小时前
从零到一打造 Vue3 响应式系统 Day 10 - 为何 Effect 会被指数级触发?
前端·vue.js