Javascript添加/删除动画类,仅动画一次

2024-02-14

尝试构建一个时间选择器,这应该使输入的变化动画化。我想通过在 CSS 中添加和删除动画类来实现这一点。问题是,它只在第一次有效。

我尝试设置一个开始时间间隔,在一定时间后删除该类,略高于动画持续时间,但这会减少每次单击时动画的动画时间,并且到第三次或第四次单击时,它不会更长的动画。

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

Codepen https://codepen.io/SkriptKiddy/pen/QWLXNNB

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>

(这里的数据属性目前没有使用)

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 的末尾),我目前没有达到预期的行为。

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


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

注意:如果没有至少 1 次迭代,动画迭代事件将永远不会触发,因此代码将不起作用!

编辑:浏览器支持classList是相当新的,所以如果您需要支持较旧的浏览器,您可以回退到不同的解决方案,或者添加一个类列表填充 https://www.npmjs.com/package/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, 如下所示:

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

接下来,我们改变swapAMPM函数来使用add元素法classList在执行交换之前添加类,以便它具有动画效果。

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");
  }
}

最后,我们需要更新 cssinfinite动画迭代,这样我们的事件就会触发。

.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 https://codepen.io/r3wt/pen/WNeqxeB

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Javascript添加/删除动画类,仅动画一次 的相关文章

  • 如何更改 Google Maps v3 API for Directions 中的开始和结束标记图像

    我使用 DirectionsRender 绘制了一条路线 但我不知道如何用我自己的标记替换通用的 Google 标记 我知道并在正常的谷歌地图情况下使用它 但发现很难用开始和结束的方向标记来做到这一点 如果这是一个愚蠢的问题 感谢您的任何建
  • 图像无法在带有 DOM 的 IE 中加载:控制台中的 7009 错误(无法解码)

    当在 IE 中的单个页面上加载许多图像时 在 IE11 中重现 其中一些图像开始加载失败 并在控制台中出现类似以下警告的内容 DOM7009 无法解码 URL 处的图像 某些唯一的 url 当我查看网络流量时 似乎确实从服务器收到了每个图像
  • 最大宽度调整以适应文本?

    不是最好的标题 但无论如何 我有一个元素max width和一些文字 如果文本长度超过一行所能容纳的长度 我会得到以下结果 My text here hello everyone 换句话说 它占据了完整的最大宽度 但由于单词向下移动 右侧有
  • 隐藏 Div 的父级

    我只是想隐藏父divcomments section div class content content green div div div 我试过这个 document getElementById comments section pa
  • React-Redux:state.setIn() 和 state.set() 有什么区别?

    我见过使用setIn and set 在一些react redux代码中 state setIn state set 我在这里找到了一些文档https facebook github io immutable js https facebo
  • 防止 iOS 键盘在 cordova 3.5 中滚动页面

    我正在使用 Cordova 3 5 和 jQuery mobile 构建 iOS 应用程序 我在大部分应用程序中禁用了滚动功能 但是 当我选择输入字段时 iOS 键盘会打开并向上滚动页面 我不想要这个功能 由于输入足够高 键盘不会覆盖它 我
  • 将 GMT 时间转换为当地时间

    我以这种格式从我的服务器获取 GMT 时间 Fri 18 Oct 2013 11 38 23 GMT 我的要求是使用Javascript将此时间转换为本地时间 例如 如果用户来自印度 首先我需要采用时区 5 30并将其添加到我的服务器时间并
  • 如何制作没有 ng-repeat 的模板并使用 Angular-drag-and-drop-lists 将数据传递到 $scope?

    我想用角度拖放列表 https github com marceljuenemann angular drag and drop lists使用我自己的网格模板到所见即所得编辑器 如何构建我自己的 HTML 模板而不需要ng repeat因
  • Firefox 不会在使用 jQuery AJAX 加载的内容上呈现 CSS 样式

    我有一个网站 允许用户对书籍和文章发表评论 主表单有一个搜索输入 用于查找相关书籍或文章 来源 我使用 jQuery 根据输入的搜索词从外部站点动态加载新源 然后还使用 AJAX 返回列表中的源 我有两个问题 现在 在用户输入四个字符后 j
  • 为什么我们在打字稿中使用 HTMLInputElement ?

    我们为什么使用 document getElementById ipv as HTMLInputElement value 代替 document getElementById ipv value 功能getElementById返回具有类
  • 页面上使用 HTML Editor Extender 进行回发会导致 IE11 中出现 JavaScript 错误

    我已将 HTML 编辑器扩展程序添加到我正在处理的页面中 现在每当我在页面上发回帖子时 都会收到以下 Javascript 错误 JavaScript 运行时错误 参数无效 之后什么也没有发生 这在 IE10 或更低版本以及我所知道的所有其
  • Vuejs 2:去抖动不适用于手表选项

    当我在 VueJs 中反跳此函数时 如果我提供毫秒数作为原语 它就可以正常工作 但是 如果我将其提供为对 prop 的引用 它会忽略它 这是道具的缩写版本 props debounce type Number default 500 这是不
  • 从数据库检查数据的异步解决方案各种循环子句

    我想要做的是异步检查数据库并从中获取结果 在我的应用程序中我试图实现Asynchronously将此步骤解决为 从数据库中检查手机号码JsonArray循环子句的种类 Create JsonArray从结果 打印创建的数组 我学到了足够多的
  • 如何创建适合屏幕宽度的等宽/高框? [复制]

    这个问题在这里已经有答案了 我正在尝试建立一个网站 其中有很多宽度和高度相等的框 例如 我有一个页面 其中并排有两个相同大小的框 简单的解决方案是将宽度和高度设置为 50vw 这在出现滚动条之前效果很好 我已经用谷歌搜索了几个小时 但无法理
  • Three.js 各种大小的粒子

    我是 Three js 的新手 正在尝试找出添加 1000 个粒子的最佳方法 每个粒子都有不同的大小和颜色 每个粒子的纹理是通过绘制画布创建的 通过使用粒子系统 所有粒子都具有相同的颜色和大小 为每个粒子创建一个粒子系统是非常低效的 有没有
  • 代码镜像错误:未捕获错误:扩展集中无法识别扩展值([对象对象])

    全部 我目前正在从事一个React Electron项目 该项目的目标是完成一个Markdown编辑器 当我配置codemirror 该程序报告错误说 Uncaught Error Unrecognized extension value
  • 如何用另一个响应替换窗口的 URL 哈希?

    我正在尝试使用替换方法更改哈希 URL document location hash 但它不起作用 function var anchor document location hash this returns me a string va
  • HTML 锚点,禁用样式

    我有一些 html 锚链接代码 与文档的其余部分不同 我希望它看起来不是链接 有没有一种简单的方法可以禁用由于将文本包装在锚标记中而引起的样式更改 而不必强行使其相同 即 如果我更改正文字体样式 我不必也更改其他一些 link东西 将颜色设
  • Vue.js[vuex] 如何从突变中调度?

    我有一个要应用于 json 对象的过滤器列表 我的突变看起来像这样 const mutations setStars state payload state stars payload this dispatch filter setRev
  • CSS溢出文本显示在几行中,没有断字

    我有一些长文本显示在 div 中 该 div 具有固定的宽度和高度 我希望文本显示在几行上 作为 div 高度 并且句子单词不会中断 一行中的单词前缀和下一行中的继续 此外 我想在末尾添加省略号最后一句话 CSS white space n

随机推荐