JavaScript CSS动画只能执行一次

4
我有一个银行应用程序,有一个超级酷的手把硬币放进小猪储钱罐里。问题是,这只手只会放一次硬币就停止工作了。
以下是我的代码:
* {
  margin:0px;
  padding:0px;
}

body {
  background-image:url('../images/bg.png');
}

@keyframes moveDown {
  0% {}
  100% {margin-top:-220px;}
}

@keyframes fadeIn {
  0% {opacity:0;}
  90%{opacity:1}
  100%{opacity:0;}
}

#hand {
  height:300px;
  width:300px;
  position:absolute;
  left:50%;
  margin-left:-120px;
  margin-top:-350px;
  background-image:url("../images/hand.png");
  opacity:0;
}

#pigBox {
  margin-left:auto;
  margin-right:auto;
  height:600px;
  width:500px;
  margin-top:250px;
  position:relative;

  img {
    margin:0px 50px;
  }

}

input[type=text] {
  float:left;
  display:block;
  font-size:2em;
  width:500px;
  border-radius:10px;
  border:solid 2px pink;
  margin-top:10px;
  font-family: 'Gochi Hand', cursive;
  text-align:center;
  padding:2px;
}

#deposit {
  float:left;
  display:block;
  font-family: 'Gochi Hand', cursive;
  font-size:2em;
  clear:left;
  width:200px;
  margin:10px 25px;
  border-radius:10px;
  background-color:pink;
  border:solid 2px pink;
  padding:2px;
  cursor:pointer;

  &:hover {
    background-color:white;
  }
}

#withdraw {
  float:left;
  display:block;
  font-family: 'Gochi Hand', cursive;
  font-size:2em;
  width:200px;
  margin:10px 25px;
  border-radius:10px;
  background-color:pink;
  border:solid 2px pink;
  padding:2px;
  cursor:pointer;

  &:hover {
    background-color:white;
  }
}

label {
  text-align:center;
  display:block;
  font-family: 'Gochi Hand', cursive;
  font-size:2.5em;
  border-radius:10px;
  width:300px;
  margin-left:100px;
  margin-right:100px;
  margin-top:5px;
  margin-bottom:-15px;
}

document.getElementById('balance').value = "1000"

var balance = document.getElementById('balance').value;
var deposit = document.getElementById('deposit');
var withdraw = document.getElementById('withdraw');
var hand = document.getElementById('hand');

deposit.addEventListener('click', depositCash);
withdraw.addEventListener('click', withdrawCash);

function depositCash() {
  var depositAmt = prompt('How much would you like to deposit?');

  if(depositAmt != Number(depositAmt)) {
    return alert('Please enter a valid integer.');
  }
  else if (Number(depositAmt) < 0) {
    return alert('Please enter a positive integer.');
  }

  hand.style.animation = 'moveDown 1.5s ease-in-out, fadeIn 1.5s ease-in-out';
  balance = Number(balance) + Number(depositAmt);
  document.getElementById('balance').value = balance;
}

function withdrawCash() {
  var withdrawAmt = prompt('How much you you like to withdraw?');

  if(withdrawAmt != Number(withdrawAmt)) {
    return alert('Please enter a valid integer.');
  }
  else if (Number(withdrawAmt) < 0) {
    return alert('Please enter a positive integer.');
  }
  else if(withdrawAmt > balance) {
    return alert("Your balance isn't large enough to withdraw that amount!")
  }


  balance = Number(balance) - Number(withdrawAmt);
  document.getElementById('balance').value = balance;
}

<section id="pigBox">
      <div id="hand"></div><!-- end of hand-->
      <img src="images/pig.png" />
      <label>Balance: </label><input type="text" id="balance" />
      <button id="deposit"> Deposit </button>
      <button id="withdraw"> Withdraw </button>
  </section><!-- end of pigBox-->

<a href="http://imgur.com/FxwmGFi"><img src="http://i.imgur.com/FxwmGFi.png" title="source: imgur.com" /></a>

请注意,当您将钱存入小猪储钱罐时,手的样式会发生动画效果。大家有什么想法吗?谢谢!

1
请提供一个自我包含的示例好吗?我也想看到超酷的手 :-) - Christoph
我如何在这里托管我的图片和 CSS ;) - Brixsta
1
@Brixsta 你可以在问题中添加图片,并且它应该为图片分配一个 imgur 链接。至于 CSS,只需像你在 JavaScript 和 HTML 中那样发布即可。 - freginold
1
如果您不想上传图像,也可以使用数据URI和CSS背景图像来创建虚假图像。 - John Vandivier
@Brixsta,你还有另一个问题...第一次运行代码时,它会将余额作为字符串获取,因此如果您最初尝试提款(任何> 1的金额),它将显示您没有足够的$。使用parseInt()包装您的“balance”变量即可解决该问题。 - freginold
4个回答

4

这是因为CSS动画不会自动重新开始,尤其是因为你没有定义时间循环,所以它只执行一次。

一种方法是使用.addClass('x').removeClass('x')来重新触发在类X上定义的动画。

.addClass()当然是jQuery。您可以使用原始JS进行相同操作,例如hand.className += ' my-animation'; 并像下面一样在方法顶部重置。

//ref: https://css-tricks.com/restart-css-animation/

document.getElementById('balance').value = "1000"

var balance = document.getElementById('balance').value;
var deposit = document.getElementById('deposit');
var withdraw = document.getElementById('withdraw');
var hand = document.getElementById('hand');

deposit.addEventListener('click', depositCash);
withdraw.addEventListener('click', withdrawCash);

function depositCash() {
  hand.className = 'randoImage';
  var depositAmt = prompt('How much would you like to deposit?');

  if(depositAmt != Number(depositAmt)) {
    return alert('Please enter a valid integer.');
  }
  else if (Number(depositAmt) < 0) {
    return alert('Please enter a positive integer.');
  }

  hand.className += ' my-animation';
  balance = Number(balance) + Number(depositAmt);
  document.getElementById('balance').value = balance;
}

function withdrawCash() {
  var withdrawAmt = prompt('How much you you like to withdraw?');

  if(withdrawAmt != Number(withdrawAmt)) {
    return alert('Please enter a valid integer.');
  }
  else if (Number(withdrawAmt) < 0) {
    return alert('Please enter a positive integer.');
  }
  else if(withdrawAmt > balance) {
    return alert("Your balance isn't large enough to withdraw that amount!")
  }


  balance = Number(balance) - Number(withdrawAmt);
  document.getElementById('balance').value = balance;
}
.randoImage {
  width: 25px;
  height: 25px;
  background-image: url(data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7);
}

* {
  margin:0px;
  padding:0px;
}

@keyframes moveDown {
  0% {}
  100% {margin-top:-220px;}
}

@keyframes fadeIn {
  0% {opacity:0;}
  90%{opacity:1}
  100%{opacity:0;}
}

#hand {
  height:300px;
  width:300px;
  position:absolute;
  left:50%;
  margin-left:-120px;
  margin-top:-350px;
  /*background-image:url("../images/hand.png");*/
  opacity:0;
}

#pigBox {
  margin-left:auto;
  margin-right:auto;
  height:600px;
  width:500px;
  margin-top:250px;
  position:relative;

  img {
    margin:0px 50px;
  }

}

input[type=text] {
  float:left;
  display:block;
  font-size:2em;
  width:500px;
  border-radius:10px;
  border:solid 2px pink;
  margin-top:10px;
  font-family: 'Gochi Hand', cursive;
  text-align:center;
  padding:2px;
}

#deposit {
  float:left;
  display:block;
  font-family: 'Gochi Hand', cursive;
  font-size:2em;
  clear:left;
  width:200px;
  margin:10px 25px;
  border-radius:10px;
  background-color:pink;
  border:solid 2px pink;
  padding:2px;
  cursor:pointer;

  &:hover {
    background-color:white;
  }
}

#withdraw {
  float:left;
  display:block;
  font-family: 'Gochi Hand', cursive;
  font-size:2em;
  width:200px;
  margin:10px 25px;
  border-radius:10px;
  background-color:pink;
  border:solid 2px pink;
  padding:2px;
  cursor:pointer;

  &:hover {
    background-color:white;
  }
}

label {
  text-align:center;
  display:block;
  font-family: 'Gochi Hand', cursive;
  font-size:2.5em;
  border-radius:10px;
  width:300px;
  margin-left:100px;
  margin-right:100px;
  margin-top:5px;
  margin-bottom:-15px;
}

.my-animation {
  animation: moveDown 1.5s ease-in-out, fadeIn 1.5s ease-in-out;
}
<section id="pigBox">
      <div class="randoImage" id="hand"></div><!-- end of hand-->
      <img class="randoImage" />
      <!--<img src="images/pig.png" />-->
      <label>Balance: </label><input type="text" id="balance" />
      <button id="deposit"> Deposit </button>
      <button id="withdraw"> Withdraw </button>
  </section><!-- end of pigBox-->


1
你的解决方案只执行一次。使用IE11。 - freginold
2
已修复,我认为,请检查。现在不需要jQuery! - John Vandivier
它运行得非常好。你能详细说明一下逻辑吗?为什么 hand.className = randomImage; 这么有效?是因为它以某种方式刷新了 hand div 吗? - Brixsta
1
hand.className = 'randoImage'; 实际上是在移除 'my-animation' 类。下次添加 'my-animation' 时,它会重新触发动画。 - John Vandivier

2

在动画后,您应该删除手的样式(将3行代码添加到您的脚本中):

...

var myHand = false;

deposit.addEventListener('click', depositCash);

withdraw.addEventListener('click', withdrawCash);

function depositCash() {

if (myHand) clearTimeout(myHand);

...

hand.style.animation = 'moveDown 1.5s ease-in-out, fadeIn 1.5s ease-in-out';

balance = Number(balance) + Number(depositAmt);

document.getElementById('balance').value = balance;

myHand = setTimeout(function(){hand.style.animation = '';}, 2000);

}


0

遇到了同样的问题。

对于那些使用jQuery的人,这是我的解决方案。

我发现如果我们将.addClass().removeClass()串在一起,jQuery会解释并否定这两个命令,导致没有变化。所以我建议使用Timeout函数来解决:

let animationTimeout

clearTimeout( animationTimeout )

$('#animatedElement').addClass('animation')

animationTimeout = setTimeout(() => { $('#animatedElement').removeClass('animation')}, animationDuration)

动画超时= setTimeout(()=>{ $('#animatedElement').removeClass('animation')}, 动画持续时间)


0
一个快速简单的解决方案,使用动画 SVG,是通过加载带有随机查询的图像,例如:
假设在现有的 JavaScript 环境中存在一个名为 loadImage 的函数, loadImage('image.svg?u='+new Date().getMilliseconds());
你可以欺骗浏览器,让它认为这不是同一个文件,从而开始动画。

不是 .gif 更好的解决方案吗?你不是在产生不必要的流量吗? - Leo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接