首页 > 其他分享 >【vue2】实现css动效逐个顺序展示的效果(简陋版)

【vue2】实现css动效逐个顺序展示的效果(简陋版)

时间:2023-10-12 18:14:04浏览次数:35  
标签:index top width 动效 &. vue2 rem css activeGif

效果(进入预约里程碑模块后,小人从第一个台阶逐个闪烁出现在当前预约等级之前的台阶并消失,最终停留在当前预约等级的台阶上):

 

虽然很low但是!就是这么设计的!于是在原本静态的代码上稍加了些修改(为什么,为什么,想问天问大地)

首先是台阶部分的代码:

    <div :class="$style.reserveBox">
      <ul :class="$style.reserveList">
        <li
          v-for="(el, index) in list"
          :key="index"
          :class="[
            $style.reserveItem,
            $style[`item_${index}`],
            active === index ? $style.active : '',
            anim === index ? $style.anim : '',
            activeGif === index ? $style.activeGif : '',
          ]"
        >
          <img
            :src="active >= index ? list[index].active : list[index].default"
            :class="$style.reserveItemImg"
            @click="showPop(index)"
          />
        </li>
      </ul>
      <div :class="$style.reserveProgress">
        <img src="./images/progress.png" :class="$style.reserveProgressBg" />
        <div
          :class="$style.reserveProgressLine"
          :style="{ width: progress + '% !important' }"
        ></div>
        <img
          src="./images/line_btn.png"
          :class="$style.progress_30"
          v-show="active >= 2"
        />
        <img
          src="./images/line_btn.png"
          :class="$style.progress_50"
          v-show="active >= 3"
        />
        <img
          src="./images/line_btn.png"
          :class="$style.progress_100"
          v-show="active >= 4"
        />
      </div>
      <div :class="$style.reserveDes"></div>
    </div>

  

每个台阶都是ul中的一个li元素,li中的img元素是柱子的状态图(分别是未达到和已达到的不同效果)(这不重要),动态的小人和对话框是用伪元素写的,样式代码:

.reserveBox {
    position: absolute;
    bottom: 15.8%;
    left: 50%;
    transform: translateX(-50%);
    box-sizing: border-box;
    .reserveDes {
      position: absolute;
      right: 0;
      bottom: -0.76rem;
      width: 3.3rem;
      height: 0.25rem;
      .background-fill("./images/reserve_des.png");
    }
    .reserveList {
      width: 100%;
      display: flex;
      justify-content: center;
      align-items: end;
      .reserveItem {
        position: relative;
        .reserveItemImg {
          width: 100%;
        }
        &.activeGif::before {
          .size(0.85rem, 1.08rem);
          .background-fill("./images/man.png");

          content: "";
          display: block;
          position: absolute;
          top: 0;
          left: 50%;
          transform: translateX(-50%);
          z-index: 1;
          animation: jump 0.9s ease infinite;
        }
        &.activeGif::after {
          .size(1.34rem, 0.82rem);
          .background-fill("./images/talk.png");

          content: "";
          display: block;
          position: absolute;
          top: 0;
          left: 44%;
          z-index: 1;
          animation: shake 1s ease infinite;
        }
        &.anim::before {
          .size(0.85rem, 1.08rem);
          .background-fill("./images/man.png");

          content: "";
          display: block;
          position: absolute;
          top: 0;
          left: 50%;
          transform: translateX(-50%);
          z-index: 1;
          animation: anim 1.5s ease;
          animation-iteration-count: 1;
        }
      }
      .item_0 {
        width: 1.66rem;
        height: 1.746rem;
        &.activeGif::before {
          top: -0.25rem;
        }
        &.anim::before {
          top: -0.25rem;
        }
        &.activeGif::after {
          top: -0.75rem;
        }
      }
      .item_1 {
        width: 2.25rem;
        height: 2.5rem;
        margin-left: -0.12rem;
        &.activeGif::before {
          top: -0.54rem;
        }
        &.anim::before {
          top: -0.54rem;
        }
        &.activeGif::after {
          top: -1.1rem;
        }
      }
      .item_2 {
        width: 2.26rem;
        height: 3.77rem;
        margin-left: -0.01rem;
        &.activeGif::before {
          top: -0.3rem;
        }
        &.anim::before {
          top: -0.3rem;
        }
        &.activeGif::after {
          top: -0.8rem;
        }
      }
      .item_3 {
        width: 2.4rem;
        height: 4.79rem;
        margin-left: -0.08rem;
        &.activeGif::before {
          top: -0.04rem;
        }
        &.anim::before {
          top: -0.04rem;
        }
        &.activeGif::after {
          top: -0.46rem;
        }
      }
      .item_4 {
        width: 2.4rem;
        height: 6.17rem;
        margin-left: -0.01rem;
        &.activeGif::before {
          top: 0.6rem;
        }
        &.anim::before {
          top: 0.6rem;
        }
        &.activeGif::after {
          top: 0.1rem;
        }
      }
    }

    .reserveProgress {
      position: relative;
      width: 10.8rem;
      height: 0.94rem;
      z-index: 1;
      .reserveProgressBg {
        width: 100%;
        height: 100%;
      }
      .reserveProgressLine {
        background-image: url("./images/line_only.png");
        background-position: left top;
        background-size: 8.92rem 0.72rem;
        background-repeat: no-repeat;
        position: absolute;
        display: inline-block;
        left: 0.26rem;
        top: 0.1rem;
        width: 8.92rem;
        height: 0.72rem;
        z-index: 1;
      }
      .progress_30 {
        position: absolute;
        top: 0.054rem;
        left: 41%;
        height: 0.72rem;
        width: auto;
        z-index: 2;
      }
      .progress_50 {
        position: absolute;
        top: 0.054rem;
        left: 63%;
        height: 0.72rem;
        width: auto;
        z-index: 2;
      }
      .progress_100 {
        position: absolute;
        top: 5.4px;
        left: 85%;
        height: 0.72rem;
        width: auto;
        z-index: 2;
      }
    }
  }

  

css3效果代码:

@keyframes shake {
  10% {
    transform: rotate(15deg);
  }
  20% {
    transform: rotate(-10deg);
  }
  30% {
    transform: rotate(5deg);
  }
  40% {
    transform: rotate(-5deg);
  }
  50%,
  100% {
    transform: rotate(0deg);
  }
}
@keyframes jump {
  10% {
    transform: translate(-50%, 2px);
  }
  100% {
    transform: translate(-50%, 0);
  }
}
@keyframes anim {
  0% {
    opacity: 1;
  }
  40% {
    opacity: 0;
  }
  70% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

  

由于是在原本静态的代码上删删改改,所以只是一个简陋的方案,思路就是在data中配置3个值作为控制:

anim:用来控制当前哪个元素需要闪烁出现并消失 active:当前预约等级 activeGif:当前需要展示小人跳动和对话框的预约等级(也就是动效结束后小人停留在哪个预约阶段的台阶上) 这三个元素的取值均由0开始,对应li遍历的index。初始值-1,不展示任何效果。 同时,还需要定义一个timer初始值伪null。 写一个方法:
    showAni() {
      const _this = this;
      clearTimeout(this.timer);
      let count = 0;
      const length = this.list.filter((_, index) => index < this.active).length;
      function changeContent() {
        if (count < length) {
          _this.anim = count;
          count += 1;
          _this.timer = setTimeout(changeContent, 1500);
        } else {
          _this.anim = -1;
          clearTimeout(this.timer);
          if (count != -1 && count === length) {
            _this.activeGif = _this.active;
          }
        }
      }
      if (count < length) {
        changeContent();
      }
    },

  

这个方法就是实现小人整体动画的核心。

在watch中监听当前是否处在里程碑这一屏:

  watch: {
    activePage(newVal) {
      if (newVal && newVal === 1) {
        this.$nextTick(() => {
          clearTimeout();
          setTimeout(() => {
            this.showAni(newVal);
          }, 500);
        });
      } else {
        this.$nextTick(() => {
          this.anim = -1;
          this.activeGif = -1;
        });
      }
    },
  },

  

这个activePage是父组件传来的,当对应到里程碑的index时,清除定时,并在500ms后执行动画,这个延时是为了保证不在用户刚进入这一屏时就已经开始执行第一次闪烁,视觉效果太仓促。同时,当当前没有展示里程碑这一屏时,设置anim和activeGif为初始值-1,保证当前没有元素处在动效中。

在执行showAni方法时,定义了一个当前count为0,也就是从第一个li的动效开始展示,我们的闪烁动效只需要展示到当前阶段之前就可以停了,所以count+1的操作只执行到当前阶段之前的index,待count+1后等于当前阶段的index,就给当前阶段的元素执行activeGif动画,也就是上下跳动+对话框,动效也就至此完成了。

做完这个之后我突然觉得,是不是做一个小人从第一个逐个跳到当前阶段的台阶还更简单点??可恶啊一个官网能不能少搞点这种花里胡哨的登西!做个gif拿来展示多好!(毕竟做完之后看了眼浏览器内存用量竟高达250mb,真的有点牛)

吐槽完毕,记录一下,方便以后copy嘻嘻

 

标签:index,top,width,动效,&.,vue2,rem,css,activeGif
From: https://www.cnblogs.com/nangras/p/17760201.html

相关文章

  • S12700 CSS主备倒换
    导致集群主备倒换的原因较多,在此主要介绍由于主控板故障引起的主备倒换以及通过命令行执行的主备倒换。主控板故障引起的主备倒换集群系统主控板的故障可能会引起集群系统内角色的变化。集群系统主用主控板故障集群系统主用主控板故障后,集群系统角色的变化如图3-21所示。图3-21 集......
  • vue2常见选项和生命周期钩子函数
    Vue2提供了一些其他选项和钩子函数,以支持更高级的组件功能和配置,这些包括:data:data选项用于定义组件的响应式数据。这些数据将被Vue追踪,以便在数据发生变化时更新视图。data(){return{message:'Hello,Vue!'}}methods:methods选项用于定义组件的方法,这些方法......
  • vue2 父传子,子传父
    在Vue2中,使用props来从父组件向子组件传递数据,而要从子组件向父组件传递数据,通常需要使用自定义事件。关键字分别是:从父组件向子组件传递数据(父传子):props:可以在子组件中使用props来接收父组件传递的数据。在父组件中,使用子组件标签的属性来传递数据。示例:<!--父组件--......
  • css伪类和伪元素
    一、伪类说明  定义:伪类⽤于向某些选择器添加特殊的效果  超链接(a标签)伪类:a标签我们在日常工作和学习中用的很多,我们只知道默认状态下为蓝色,但是a标签其实有四种状态。    1、未访问前为蓝色(如果a标签使用不是蓝色而是紫色,那么近期访问过该网站,需要去浏览器删除近期记......
  • 使用HTML和CSS做出心形图案
    今天我们要做一个心形图案,闲来无事可以尝试做一些其他图案。也可以用来逗心爱的女孩开心。例如:先看步骤先给正方形上方和右方两侧做两个圆圆的做法就是border-radius:50%,就是圆形了最后给他们翻转45°下面是整体代码,大家想尝试直接复制到自己代码中<!DOCTYPEhtml><htmllang="en......
  • 记录--纯CSS实现骚气红丝带
    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助在本文中,我们将探讨如何使用CSS以最少的代码创造出精美的CSS丝带形状,并最终实现下面这个效果:下面我们使用html和css来实现这个效果。我们使用内容自适应方式布局,不用担心里面的文字长度。本文介绍两种丝带:左......
  • 开局就集成tailwindcss(一)
    1.使用cli创建项目npmcreatevite@latest项目名--templatereact-ts 2.因为css功底偏弱,所以必须也是完全有必要的,在这里必须集成一下tailwindcss,npminstalltailwindcssautoprefixerpostcss-cli#额外的安装2个配套的插件#autoprefixer自动添加样式的前缀,很......
  • CSS 多行文本超链接下划线动效
    先看效果乍一看,是不是感觉很简单,仔细一瞅发现事情好像没有那么简单。如果十分钟还没想出怎么实现,那就把简历上的“精通css”改成“了解css”……......
  • 为什么 CSS flex 布局中没有 `justify-items` 和 `justify-self`?
    为什么CSSflex布局中没有justify-items和justify-self?为什么在CSSflex布局中存在align-items和align-self,却没有justify-items和justify-self呢?要解答这个问题,首先需要理解主轴(mainaxis)和交叉轴(crossaxis)之间的差异。1.主轴和交叉轴的区别在没有折行的情况......
  • threejs CSS2DObject点击事件触发不了
    原因:在three.js  0.13X版本后,上面dom的onclick不会触发,原因是控制器Controls,可以尝试一下去掉控制器,看看dom上的点击事件是否ok letobtControls=newOrbitControls(camera,container); // OrbitControls对页面的事件进行监听,并且阻止穿透 ......