3 回答

TA貢獻(xiàn)1886條經(jīng)驗(yàn) 獲得超2個(gè)贊
我想這就是你在香草中的做法
gugateider 是對(duì)的,你需要一個(gè) setTimout,有 AnimationEvent API 但它不完全支持。
下面是一個(gè)簡化的方法:
不需要事件監(jiān)聽器或收集 ID
更新:
包括去抖動(dòng)以停止對(duì)同一按鈕的多次點(diǎn)擊
調(diào)整超時(shí)(添加超時(shí)以便值在視圖外發(fā)生變化以產(chǎn)生數(shù)字實(shí)際旋轉(zhuǎn)的錯(cuò)覺,AnimationEvent 無法檢測(cè)您是否已完成動(dòng)畫。)
<div class="wrapper">
<div id="hour" class="unit">
<div class="plus button" onClick="pressedButton(event);">+</div>
<div class="value"><div>10</div></div>
<div class="minus button" onClick="pressedButton(event);">-</div>
</div>
<div id="minute" class="unit">
<div class="plus button" onClick="pressedButton(event);">+</div>
<div class="value"><div>36</div></div>
<div class="minus button" onClick="pressedButton(event);">-</div>
</div>
<div id="meridiem" class="unit">
<div class="plus button" onClick="pressedButton(event);">+</div>
<div class="value"><div>AM</div></div>
<div class="minus button" onClick="pressedButton(event);">-</div>
</div>
</div>
.wrapper {
display: flex;
flex-flow: row no-wrap;
justify-content: space-between;
align-items: center;
width: 200px;
height: 200px;
margin: 100px auto;
background: red;
padding: 20px;
}
.unit {
display: flex;
flex-flow: column;
justify-content: space-between;
align-items: space-between;
height: 100%;
position: relative;
}
.button {
border: 2px solid black;
height: 50px;
width: 50px;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
background: grey;
&:hover {
opacity: 0.8;
}
}
.value {
border: 2px solid black;
height: 50px;
width: 50px;
font-family: sans-serif;
font-size: 20px;
display: flex;
justify-content: center;
align-items: center;
background: lightgrey;
overflow: hidden;
}
.animate {
top: 0;
position: relative;
overflow: hidden;
animation-name: downandout;
animation-duration: 1s;
animation-iteration-count: 1;
transition-timing-function: ease-in-out;
&--reverse {
animation-direction: reverse;
}
}
@keyframes downandout {
0% {top: 0}
50% {top: 50px}
51% {top: -50px}
100% {top: 0}
}
debounce = function(func, wait, immediate) {
var timeout;
return function() {
var context = this,
args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
}
pressedButton = function($event) {
$event.preventDefault();
// debouncedFn to stop multiple clicks to the same button
var debouncedFn = debounce(function() {
// All the taxing stuff you do
const target = $event.target;
const elm = target.parentNode.children[1];
let direction;
// clone the element to restart the animation
const newone = elm.cloneNode(true);
// add the first animate
newone.children[0].classList.add("animate");
// What button was pressed
if (target.classList.contains("minus")) {
direction = "down";
} else {
direction = "up";
}
// direction of animation
if (direction === "down") {
newone.children[0].classList.add("animate--reverse");
} else {
newone.children[0].classList.remove("animate--reverse");
}
// add the new element to the DOM
elm.parentNode.replaceChild(newone, elm);
// change value after half of the animation has completed
setTimeout(function() {
switch (target.parentNode.id) {
case "hour":
case "minute":
if (direction === "down") {
newone.children[0].innerText--;
} else {
newone.children[0].innerText++;
}
break;
case "meridiem":
if (newone.children[0].innerText === "PM") {
newone.children[0].innerText = "AM";
} else {
newone.children[0].innerText = "PM";
}
}
}, 100);
}, 250);
// Call my function
debouncedFn();
};
https://codepen.io/eddy14u/pen/VwZJmdW

TA貢獻(xiàn)1828條經(jīng)驗(yàn) 獲得超4個(gè)贊
您可以使用動(dòng)畫迭代事件偵聽器來檢測(cè)動(dòng)畫何時(shí)結(jié)束,并正確刪除您的類。為此,動(dòng)畫迭代必須設(shè)置為無限。在我的更改中,我還利用classList元素的屬性從元素中添加/刪除類。
注意:如果沒有至少 1 次迭代,動(dòng)畫迭代事件將永遠(yuǎn)不會(huì)觸發(fā),因此代碼將無法運(yùn)行!
編輯:瀏覽器支持classList是最近的,所以如果你需要支持舊瀏覽器,你可以回退到不同的解決方案,或者添加一個(gè)classList polyfill
首先,我們需要一個(gè)函數(shù)來檢測(cè)瀏覽器支持哪個(gè)動(dòng)畫迭代事件:
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];
}
}
}
接下來,我們需要為該事件添加一個(gè)事件偵聽器,當(dāng)?shù)|發(fā)時(shí),我們從元素的 中刪除該類classList,如下所示:
ampmEl.addEventListener(whichAnimationEvent(),function(){
console.log('ampmEl event listener fired')
ampmEl.classList.remove('animateStart');
});
接下來,我們將swapAMPM函數(shù)更改為在執(zhí)行交換之前使用add元素的方法classList添加類,使其具有動(dòng)畫效果。
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 以進(jìn)行infinite動(dòng)畫迭代,以便觸發(fā)我們的事件。
.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);
}

TA貢獻(xiàn)1951條經(jīng)驗(yàn) 獲得超3個(gè)贊
我知道 setTimeout 不是在那里使用的最佳選擇,但是由于您已經(jīng)完成了很多工作,您可以嘗試用以下代碼替換 swapAMPM 函數(shù):
function swapAMPM() {
let value = ampmEl.innerHTML;
if (ampmEl.hasAttribute("class")) {
ampmEl.removeAttribute("class");
}
setTimeout( () => {
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");
}
}, 150);
}
添加回答
舉報(bào)