Javascript添加/删除动画类,仅动画一次 [英] Javascript add/remove animation class, only animates once

查看:82
本文介绍了Javascript添加/删除动画类,仅动画一次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

试图构建一个时间选择器,该时间选择器应该可以动画化输入的变化.我以为可以通过在CSS中添加和删除动画类来做到这一点.问题是,它只能在第一次使用.

Trying to build a time picker, that is supposed to animate the change of input. I thought I'd do this by adding and removing an animation class from CSS. The problem is, that it only works the first time.

我尝试设置一个开始的时间间隔,该时间间隔是在一定时间后删除类的,略高于动画持续时间,但是每次单击以及第三次或第四次单击都减少了动画的动画时间,它不再具有动画效果.

I tried to set an interval to start with, that removed the class after a certain amount of time, slightly above the animation duration, but that reduced the animation time of the animation with each click, and by the third or fourth click, it no longer animated.

然后我只是选择检查该类是否存在以开始,将其删除以开始,然后添加它.确保每次都从头开始.但是现在,它只是第一次动画.

Then I just opted to check if the class existed to start with, remove it to start with, then add it. To make sure it starts from scratch each time. But now it only animates the very first time.

Codepen

HTML:


    <div id="wrapper">
      <div id="uphour"></div>
      <div id="upminute"></div>
      <div id="upampm"></div>
      <div class="animated">
        <div id="hour" data-hour="1">2</div>
      </div>
      <div class="animated">
        <div id="minute" data-minute="1">50</div>
      </div>
      <div class="animated">
        <div id="ampm" data-minute="AM">AM</div>
      </div>
      <div id="downhour"></div>
      <div id="downminute"></div>
      <div id="downampm"></div>
      </div>

(此处的数据属性当前未使用)

(the data attributes here are not currently in use)

SCSS:


    $finger: 2cm;
    $smallfinger: .3cm;

    #wrapper {
      display: grid;
      grid-template-columns: $finger $finger $finger;
      grid-template-rows: $finger $finger $finger;
      grid-column-gap: $smallfinger;
      grid-row-gap: $smallfinger;
      position:absolute;
      width: 100vw;
      background: #FF00FF;
      height: calc( (#{$finger} * 3) + (#{$smallfinger} * 4) );
      box-sizing: border-box;
      bottom:$finger;
      left:0;
      padding:0;
      margin:0;
      align-content: center;
      justify-content: center;
      }

    #uphour,
    #upminute,
    #upampm,
    #downhour,
    #downminute,
    #downampm {
      display: flex;
      background: rgba(255,0,0,.4);
      width: $finger;
      height: $finger;
      margin-left: 1vw;
      margin-right: 1vw;
      border: 1px solid black;
    }

    .animated {
      display: flex;
      width: $finger;
      height: $finger;
      margin-left: 1vw;
      margin-right: 1vw;
      border: 1px solid black;
      overflow:hidden;
    }


    #minute, #hour, #ampm {
      display: flex;
      /*background: rgba(255,0,0,.4); for testing of animation only*/
      width: $finger;
      height: $finger;
      border: 0;
      position: relative;
      align-items: center;
      justify-content: center;
      font-size: .8cm;
    }

    .animateStart {
      -webkit-animation-name: downandout; /* Safari 4.0 - 8.0 */
      animation-name: downandout;
      -webkit-animation-duration: 250ms; /* Safari 4.0 - 8.0 */
      animation-duration: 250ms;
      /*-webkit-animation-iteration-count: infinite;
      animation-iteration-count: infinite;*/
      transition-timing-function: cubic-bezier(1,0,0,1);
    }

    /* Safari 4.0 - 8.0 */
    @-webkit-keyframes downandout {
      0%   {top: 0; left: 0;}
      10%  {top: 100%; left:0;}
      50%  {top: 100%; left: 100%;}
      90% {top: -100%; left:100%;}
    }

    /* Standard syntax */
    @keyframes downandout {
      0%   {top: 0; left: 0;}
      40%  {top: 100%; left:0;}
      42%  {top: 100%; left: calc(#{$finger} * 2);}
      48% {top: -110%; left: calc(#{$finger} * 2);}
      50% {top: -110%; left:0;}
      100% {top: 0; left:0;}
    }

Javascript:


    var uphourEl = document.getElementById("uphour");
    var downhourEl = document.getElementById("downhour");
    var upminuteEl = document.getElementById("upminute");
    var downminuteEl = document.getElementById("downminute");
    var upampmEl = document.getElementById("upampm");
    var downampmEl = document.getElementById("downampm");

    uphourEl.addEventListener("click", increaseHour);
    downhourEl.addEventListener("click", decreaseHour);
    upminuteEl.addEventListener("click", increaseMinute);
    downminuteEl.addEventListener("click", decreaseMinute);
    upampmEl.addEventListener("click", swapAMPM);
    downampmEl.addEventListener("click", swapAMPM);

    var hourEl = document.getElementById("hour"); 
    var minuteEl = document.getElementById("minute"); 
    var ampmEl = document.getElementById("ampm"); 

    function increaseHour() {
      let value = hourEl.innerHTML;
      if (value > 11) {
          value = 1
      } else  {
        value++;
      }
      hourEl.innerHTML = value;
      console.log(value);
    }

    function decreaseHour() {
      let value = hourEl.innerHTML;
      if (value < 2) {
          value = 12
      } else  {
        value--;
      }
      hourEl.innerHTML = value;
      console.log(value);
    }

    function increaseMinute() {
      let value = minuteEl.innerHTML;
      if (value > 58) {
          value = 0
      } else  {
        value++;
      }
      minuteEl.innerHTML = value;
      console.log(value);
    }

    function decreaseMinute() {
      let value = minuteEl.innerHTML;
      if (value < 1) {
          value = 59
      } else  {
        value--;
      }
      minuteEl.innerHTML = value;
      console.log(value);
    }

    function swapAMPM() {
      let value = ampmEl.innerHTML;
      if (ampmEl.hasAttribute("class")) {
        ampmEl.removeAttribute("class");
      }
      ampmEl.setAttribute("class", "animateStart");
      if (value === "AM") {
          value = "PM";
          ampmEl.innerHTML = value;
          console.log("Changed from AM");
      } else  {
        value = "AM";
        ampmEl.innerHTML = value;
        console.log("Changed from PM");
      }
    }

..这是swapAMPM函数(在Javascript末尾),我目前无法正常运行.

..it's the swapAMPM function (at the end of the Javascript) I'm currently not getting to behave as expected.

关于我为什么会遇到这种行为的任何建议?我缺少一些最佳实践吗?

Any suggestions on why I am experiencing this behavior? Is there some best practice I am missing?

推荐答案

您可以使用动画迭代事件侦听器来检测动画何时结束,并正确删除类.为此,必须将动画迭代设置为无穷大.在我的更改中,我还利用了元素的 classList 属性来从元素中添加/删除类.

You can use animation iteration event listener to detect when your animation has ended, and correctly remove your class. for this to work, animation iteration has to be set to infinite. in my changes, i also took advantage of the classList property of elements to add/remove the class from the element.

注意:没有至少1次迭代,动画迭代事件将永远不会触发,因此代码将无法正常工作!

浏览器对 classList 的支持是最近的,因此,如果您需要支持较旧的浏览器,则可以使用其他解决方案,或者添加

browser support for classList is fairly recent, so if you need to support older browsers you can fall back to a different solution, or add a classList polyfill

首先,我们需要一个功能来检测浏览器支持哪个动画迭代事件:

function whichAnimationEvent(){
  var el = document.createElement("fakeelement");

  var animations = {
    "animation"      : "animationiteration",
    "OAnimation"     : "oAnimationIteration",
    "MozAnimation"   : "animationiteration",
    "WebkitAnimation": "webkitAnimationIteration"
  };

  for (let t in animations){
    if (el.style[t] !== undefined){
      return animations[t];
    }
  }
}

下一步,我们需要为该事件添加一个事件侦听器,并且在迭代触发时,我们从元素的 classList 中删除该类,如下所示:

next, we need to add an event listener for that event, and when the iteration fires, we remove the class from the element's classList, as shown below:

ampmEl.addEventListener(whichAnimationEvent(),function(){
  console.log('ampmEl event listener fired')
  ampmEl.classList.remove('animateStart');
});

下一步,我们将 swapAMPM 函数更改为使用元素 classList add 方法添加类,然后再执行交换,使其具有动画效果.

next, we change the swapAMPM function to use the add method of the elements classList to add the class before performing the swap, so that it is animated.

function swapAMPM() {
  let value = ampmEl.innerHTML;
  ampmEl.classList.add('animateStart');
  if (value === "AM") {
      value = "PM";
      ampmEl.innerHTML = value;
      console.log("Changed from AM");
  } else  {
    value = "AM";
    ampmEl.innerHTML = value;
    console.log("Changed from PM");
  }
}

最后,我们需要更新css以使其具有 infinite 动画迭代,以便触发事件.

finally, we need to update the css to have infinite animation-iteration, so that our event will fire.

.animateStart {
  -webkit-animation-name: downandout; /* Safari 4.0 - 8.0 */
  animation-name: downandout;
  -webkit-animation-duration: 250ms; /* Safari 4.0 - 8.0 */
  animation-duration: 250ms;
  -webkit-animation-iteration-count: infinite;
  animation-iteration-count: infinite;
  transition-timing-function: cubic-bezier(1,0,0,1);
}

完整的示例

codepen

这篇关于Javascript添加/删除动画类,仅动画一次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆