【问题标题】:How can I force a CSS animation of an element to start from the same location as the previous animation finished?如何强制元素的 CSS 动画从与上一个动画完成的位置相同的位置开始?
【发布时间】:2022-01-05 10:35:13
【问题描述】:

我有一个图像,我想在每次单击鼠标时移动一定距离(始终相同)和特定方向(在数组中指定)。第一次单击将其移动到第一个数组元素中指定的方向,第二次单击第二个,依此类推。

除非我要求它连续两次向同一方向移动,否则这很好用。在这种情况下,它会立即移动到没有动画的结束位置,就好像它已经在那里开始了动画一样,尽管调试器显示了由 unitElement.style.left 定义的位置,与它在屏幕上的外观正确对应。

HTML,带有四个转换和一个要移动的图像:

<style>
    .unit { width: 60px; height: 60px; position: absolute; }

    @keyframes N {100% {transform: translate(0px, -60px);}}
    @keyframes E {100% {transform: translate(60px, 0px);}}
    @keyframes S {100% {transform: translate(0px, 60px);}}
    @keyframes W {100% {transform: translate(-60px, 0px);}}
</style>

<body>
    <img src="test.png" class="unit" id="F1" />
</body>

点击事件调用的函数:

function nextPulseAnimate() {
    pulse++;
    for(var index = 0; index < units.length; index++) {
    
        var unit = units[index];
        var direction = unit.moves[pulse-1]
        
        var unitElement = document.getElementById(unit.name);

        //ensure that the image is starting from the right place
        unitElement.style.left = unit.start.x;
        unitElement.style.top = unit.start.y;

        unitElement.style.animation = direction + " 2s ease-in-out forwards";
    }

    //then re-set the locations ready for next pulse
    //If this is not done, each animation will start from the unit's original location
    for(var index = 0; index < units.length; index++) {
        var unit = units[index];
        var direction = unit.moves[pulse-1]
            
        switch (direction){
         case "N":
             unit.start.y -= 60; 
             break;
         case "E": 
             unit.start.x += 60;
             break;
         case "S":
             unit.start.y += 60;
             break; 
         case "W": 
             unit.start.x -= 60;
             break;
         }
    }
}

函数中提到的“单元”来自一个全局对象数组,看起来像这样(实际上它会有几十个元素):

units = [
    {name: "F1", start: {x: 0, y: 0}, moves: ["S", "E", "E", "E"]}
];

为了完整起见,定义了另一个全局变量(并在上面使用): 脉冲 = 0

【问题讨论】:

  • 提供 css .unit 规则定义。如何。您的 img 是静态的、相对的、绝对的还是固定的?一个最小的可重现代码会非常好。
  • 当然。这是 .unit 的 css 定义: .unit { width: 60px;高度:60px;位置:绝对; }
  • 我的意思是像.unit{ position: absolute; height:20px}这样的整个css规则。更新你的开场白/问题
  • 在第二个 for 循环中,您将单位设置为固定坐标,它们实际上并不是它们的最后位置。有一个 DOM 事件 onAnimationEnd 您可以使用它来更新最后一个坐标。 developer.mozilla.org/en-US/docs/Web/API/HTMLElement/…
  • 连续两次问题:当你设置相同的动画名称时,系统不会动画,因为它认为它已经完成了。您需要清除它并以某种方式重置。

标签: javascript css animation


【解决方案1】:

这就是我的意思:

units = [{name: "F1", start: { x: '0px', y: '0px'},
    moves: ["S", "E", "E", "N", "W", "W"]
  },
  { name: "F2", start: { x: '120px', y: '60px' },
    moves: ["N", "W", "W", "S", "E", "E"]
  }
];

var pulse = 0;

function init() {
  document.body.addEventListener("click", nextPulseAnimate);

  for (var index = 0; index < units.length; index++) {
    var unit = units[index];
    var unitElement = document.getElementById(unit.name);
    unitElement.style.left = unit.start.x;
    unitElement.style.top = unit.start.y;

    unitElement.addEventListener('animationend', (event) => {
      document.body.addEventListener("click", nextPulseAnimate);
      var e = event.target;
      /* get position relative to viewport */
      var r = e.getBoundingClientRect();
      e.style.left = r.left + 'px';
      e.style.top = r.top + 'px';
      /* remove animation so that you can use it again */
      e.style.animation = 'none';
    });
  }
}

function nextPulseAnimate() {
  pulse++;
  if (pulse < 7) {
    document.getElementById('stats').innerText = 'Moves: ' + pulse + '/6';
    //don't let user click while animation is going on
    document.body.removeEventListener('click', nextPulseAnimate);
  }

  for (var index = 0; index < units.length; index++) {
    var unit = units[index];
    var direction = unit.moves[pulse - 1]
    var unitElement = document.getElementById(unit.name);
    unitElement.style.animation = direction + " 2s ease-in-out forwards";
  }
}
body {
  width: 90vw;
  height: 90vh
}

p {
  position: fixed;
  top: 40vh;
}

.unit { width: 60px; height: 60px; position: absolute; }

@keyframes N {100% {transform: translate(0px, -60px);}}
@keyframes E {100% {transform: translate(60px, 0px);}}
@keyframes S {100% {transform: translate(0px, 60px);}}
@keyframes W {100% {transform: translate(-60px, 0px);}}
<!DOCTYPE html>
<html>

<body onload="init()">
  <img src="https://dummyimage.com/60x60/000/fff.jpg" class="unit" id="F1" />
  <img src="https://dummyimage.com/60x60/a0a/fff.jpg" class="unit" id="F2" />
  <p id=stats>Click anywhere to trigger moves</p>
</body>

</html>

【讨论】:

    猜你喜欢
    • 2021-11-07
    • 1970-01-01
    • 1970-01-01
    • 2018-04-22
    • 1970-01-01
    • 1970-01-01
    • 2015-12-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多