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

试图构建一个时间选择器,它应该为输入的变化设置动画。我想我会通过从 CSS 中添加和删除动画类来做到这一点。问题是,它只在第一次有效。

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

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

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>

..它是 swapAMPM 函数(在 Javascript 的末尾)我目前没有按预期行事。

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


千万里不及你
浏览 524回答 3
3回答

MM们

我想这就是你在香草中的做法gugateider 是对的,你需要一个 setTimout,有 AnimationEvent API 但它不完全支持。下面是一个简化的方法:不需要事件监听器或收集 ID更新:包括去抖动以停止对同一按钮的多次点击调整超时(添加超时以便值在视图外发生变化以产生数字实际旋转的错觉,AnimationEvent 无法检测您是否已完成动画。)<div class="wrapper">&nbsp; <div id="hour" class="unit">&nbsp; &nbsp; <div class="plus button" onClick="pressedButton(event);">+</div>&nbsp; &nbsp; <div class="value"><div>10</div></div>&nbsp; &nbsp; <div class="minus button" onClick="pressedButton(event);">-</div>&nbsp; </div>&nbsp; &nbsp; <div id="minute" class="unit">&nbsp; &nbsp; <div class="plus button"&nbsp; onClick="pressedButton(event);">+</div>&nbsp; &nbsp; &nbsp; <div class="value"><div>36</div></div>&nbsp; &nbsp; <div class="minus button"&nbsp; onClick="pressedButton(event);">-</div>&nbsp; </div>&nbsp; &nbsp; <div id="meridiem" class="unit">&nbsp; &nbsp; <div class="plus button"&nbsp; onClick="pressedButton(event);">+</div>&nbsp; &nbsp; &nbsp; <div class="value"><div>AM</div></div>&nbsp; &nbsp; <div class="minus button"&nbsp; onClick="pressedButton(event);">-</div>&nbsp; </div></div>.wrapper {&nbsp; display: flex;&nbsp; flex-flow: row no-wrap;&nbsp; justify-content: space-between;&nbsp; align-items: center;&nbsp; width: 200px;&nbsp; height: 200px;&nbsp; margin: 100px auto;&nbsp; background: red;&nbsp; padding: 20px;}.unit {&nbsp; display: flex;&nbsp; flex-flow: column;&nbsp; justify-content: space-between;&nbsp; align-items: space-between;&nbsp; height: 100%;&nbsp; position: relative;}.button {&nbsp; border: 2px solid black;&nbsp; height: 50px;&nbsp; width: 50px;&nbsp; cursor: pointer;&nbsp; display: flex;&nbsp; justify-content: center;&nbsp; align-items: center;&nbsp; background: grey;&nbsp; &:hover {&nbsp; &nbsp; opacity: 0.8;&nbsp; }}.value {&nbsp; border: 2px solid black;&nbsp; height: 50px;&nbsp; width: 50px;&nbsp; font-family: sans-serif;&nbsp; font-size: 20px;&nbsp; display: flex;&nbsp; justify-content: center;&nbsp; align-items: center;&nbsp; background: lightgrey;&nbsp; &nbsp; overflow: hidden;}.animate {&nbsp; top: 0;&nbsp; position: relative;&nbsp; overflow: hidden;&nbsp; animation-name: downandout;&nbsp; animation-duration: 1s;&nbsp; animation-iteration-count: 1;&nbsp; transition-timing-function: ease-in-out;&nbsp; &--reverse {&nbsp; &nbsp; animation-direction: reverse;&nbsp; }}&nbsp;@keyframes downandout {&nbsp; &nbsp;0%&nbsp; {top: 0}&nbsp; &nbsp;50% {top: 50px}&nbsp; &nbsp;51% {top: -50px}&nbsp; &nbsp;100%&nbsp; {top: 0}}debounce = function(func, wait, immediate) {&nbsp; var timeout;&nbsp; return function() {&nbsp; &nbsp; var context = this,&nbsp; &nbsp; &nbsp; args = arguments;&nbsp; &nbsp; var later = function() {&nbsp; &nbsp; &nbsp; timeout = null;&nbsp; &nbsp; &nbsp; if (!immediate) func.apply(context, args);&nbsp; &nbsp; };&nbsp; &nbsp; var callNow = immediate && !timeout;&nbsp; &nbsp; clearTimeout(timeout);&nbsp; &nbsp; timeout = setTimeout(later, wait);&nbsp; &nbsp; if (callNow) func.apply(context, args);&nbsp; };}pressedButton = function($event) {&nbsp; $event.preventDefault();&nbsp; // debouncedFn to stop multiple clicks to the same button&nbsp; var debouncedFn = debounce(function() {&nbsp; &nbsp; // All the taxing stuff you do&nbsp; &nbsp; const target = $event.target;&nbsp; &nbsp; const elm = target.parentNode.children[1];&nbsp; &nbsp; let direction;&nbsp; &nbsp; // clone the element to restart the animation&nbsp; &nbsp; const newone = elm.cloneNode(true);&nbsp; &nbsp; // add the first animate&nbsp; &nbsp; newone.children[0].classList.add("animate");&nbsp; &nbsp; // What button was pressed&nbsp; &nbsp; if (target.classList.contains("minus")) {&nbsp; &nbsp; &nbsp; direction = "down";&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; direction = "up";&nbsp; &nbsp; }&nbsp; &nbsp; // direction of animation&nbsp; &nbsp; if (direction === "down") {&nbsp; &nbsp; &nbsp; newone.children[0].classList.add("animate--reverse");&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; newone.children[0].classList.remove("animate--reverse");&nbsp; &nbsp; }&nbsp; &nbsp; // add the new element to the DOM&nbsp; &nbsp; elm.parentNode.replaceChild(newone, elm);&nbsp; &nbsp; // change value after half of the animation has completed&nbsp; &nbsp; setTimeout(function() {&nbsp; &nbsp; &nbsp; switch (target.parentNode.id) {&nbsp; &nbsp; &nbsp; &nbsp; case "hour":&nbsp; &nbsp; &nbsp; &nbsp; case "minute":&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (direction === "down") {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; newone.children[0].innerText--;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; newone.children[0].innerText++;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;&nbsp; &nbsp; &nbsp; &nbsp; case "meridiem":&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (newone.children[0].innerText === "PM") {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; newone.children[0].innerText = "AM";&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; newone.children[0].innerText = "PM";&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }, 100);&nbsp; }, 250);&nbsp; // Call my function&nbsp; debouncedFn();};https://codepen.io/eddy14u/pen/VwZJmdW

明月笑刀无情

您可以使用动画迭代事件侦听器来检测动画何时结束,并正确删除您的类。为此,动画迭代必须设置为无限。在我的更改中,我还利用classList元素的属性从元素中添加/删除类。注意:如果没有至少 1 次迭代,动画迭代事件将永远不会触发,因此代码将无法运行!编辑:浏览器支持classList是最近的,所以如果你需要支持旧浏览器,你可以回退到不同的解决方案,或者添加一个classList polyfill首先,我们需要一个函数来检测浏览器支持哪个动画迭代事件:function whichAnimationEvent(){&nbsp; var el = document.createElement("fakeelement");&nbsp; var animations = {&nbsp; &nbsp; "animation"&nbsp; &nbsp; &nbsp; : "animationiteration",&nbsp; &nbsp; "OAnimation"&nbsp; &nbsp; &nbsp;: "oAnimationIteration",&nbsp; &nbsp; "MozAnimation"&nbsp; &nbsp;: "animationiteration",&nbsp; &nbsp; "WebkitAnimation": "webkitAnimationIteration"&nbsp; };&nbsp; for (let t in animations){&nbsp; &nbsp; if (el.style[t] !== undefined){&nbsp; &nbsp; &nbsp; return animations[t];&nbsp; &nbsp; }&nbsp; }}接下来,我们需要为该事件添加一个事件侦听器,当迭代触发时,我们从元素的 中删除该类classList,如下所示:ampmEl.addEventListener(whichAnimationEvent(),function(){&nbsp; console.log('ampmEl event listener fired')&nbsp; ampmEl.classList.remove('animateStart');});接下来,我们将swapAMPM函数更改为在执行交换之前使用add元素的方法classList添加类,使其具有动画效果。function swapAMPM() {&nbsp; let value = ampmEl.innerHTML;&nbsp; ampmEl.classList.add('animateStart');&nbsp; if (value === "AM") {&nbsp; &nbsp; &nbsp; value = "PM";&nbsp; &nbsp; &nbsp; ampmEl.innerHTML = value;&nbsp; &nbsp; &nbsp; console.log("Changed from AM");&nbsp; } else&nbsp; {&nbsp; &nbsp; value = "AM";&nbsp; &nbsp; ampmEl.innerHTML = value;&nbsp; &nbsp; console.log("Changed from PM");&nbsp; }}最后,我们需要更新 css 以进行infinite动画迭代,以便触发我们的事件。.animateStart {&nbsp; -webkit-animation-name: downandout; /* Safari 4.0 - 8.0 */&nbsp; animation-name: downandout;&nbsp; -webkit-animation-duration: 250ms; /* Safari 4.0 - 8.0 */&nbsp; animation-duration: 250ms;&nbsp; -webkit-animation-iteration-count: infinite;&nbsp; animation-iteration-count: infinite;&nbsp; transition-timing-function: cubic-bezier(1,0,0,1);}

饮歌长啸

我知道 setTimeout 不是在那里使用的最佳选择,但是由于您已经完成了很多工作,您可以尝试用以下代码替换 swapAMPM 函数:function swapAMPM() {&nbsp;let value = ampmEl.innerHTML;&nbsp;if (ampmEl.hasAttribute("class")) {&nbsp; &nbsp; &nbsp;ampmEl.removeAttribute("class");&nbsp;}&nbsp;setTimeout( () => {&nbsp;&nbsp; &nbsp; &nbsp;ampmEl.setAttribute("class", "animateStart");&nbsp; &nbsp; &nbsp;if (value === "AM") {&nbsp; &nbsp; &nbsp; value = "PM";&nbsp; &nbsp; &nbsp; ampmEl.innerHTML = value;&nbsp; &nbsp; &nbsp; console.log("Changed from AM");&nbsp; &nbsp; &nbsp;} else&nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; value = "AM";&nbsp; &nbsp; &nbsp; &nbsp; ampmEl.innerHTML = value;&nbsp; &nbsp; &nbsp; &nbsp; console.log("Changed from PM");&nbsp; &nbsp; }&nbsp;&nbsp;}, 150);}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript