Завершение анимации css перед запуском новой - PullRequest
0 голосов
/ 28 апреля 2020

Я пытаюсь создать движущееся изображение при зависании и не зависании. Анимация должна проходить в одном направлении, когда указатель мыши находится над изображением, и в другом случае, когда указатель мыши покидает изображение.

Для этого в настоящее время я использую анимацию css со спрайтом изображения. Проблема заключается в том, что, когда мышь перемещается над изображением или покидает его до того, как пройдет время анимации (1 секунда), тогда всплеск изображения перейдет к началу следующей анимации без завершения предыдущей анимации.

Я пробовал различные способы решения этой проблемы, но я просто не могу заставить его работать (да, это мой текущий недостаток навыков). Как можно сделать так, чтобы анимация всегда заканчивалась sh перед началом новой?

http://jsfiddle.net/16jync0h/latest

HTML

<div id="navOpen"></div>

CSS

#navOpen {
  width: 64px;
  height: 64px;
  background: url('https://i.postimg.cc/hv0L4vsL/css-sprites.png') no-repeat left/cover;
}

.navOpenPlay {
  animation: Play 1s steps(24) 1 forwards;
}

.navOpenPlayBack {
  animation: PlayBack 1s steps(24) 1 backwards;
}

@keyframes Play {
  0% {
    background-position: 0px;
  }

  100% {
    background-position: -1536px;
  }
}

@keyframes PlayBack {
  0% {
    background-position: -1536px;
  }

  100% {
    background-position: 0px;
  }
}

Javascript / Jquery

 $("#navOpen").mouseover(function() {
   $(this).removeClass("navOpenPlayBack").addClass("navOpenPlay");
 });
 $("#navOpen").mouseout(function() {
   $(this).removeClass("navOpenPlay").addClass("navOpenPlayBack");
 });

Ответы [ 2 ]

0 голосов
/ 28 апреля 2020

Как упомянуто @NoSkill, вы можете использовать событие onanimationend для прослушивания после завершения анимации и добавления туда своих пользовательских логи c.

Затем вы можете объедините это с очередью, чтобы отследить, что в данный момент анимируется и что анимировать дальше.

См. пример:

let isAnimating = false;
const animationQueue = [];

function queueAnimation(cssClass) {
  animationQueue.push(cssClass);
  if (!isAnimating) {
    triggerAnimation();
  }
}

function triggerAnimation() {
  const cssClass = animationQueue.shift();
  if (cssClass) {
    $("#navOpen").attr('class', '').addClass(cssClass);
    isAnimating = true;
  }
}

$("#navOpen").mouseover(function() {
  queueAnimation('navOpenPlay');
});
$("#navOpen").mouseout(function() {
  queueAnimation('navOpenPlayBack');
});
$("#navOpen").on("animationend", function() {
  isAnimating = false;
  triggerAnimation();
});
#navOpen {
  width: 64px;
  height: 64px;
  background: url('https://i.postimg.cc/hv0L4vsL/css-sprites.png') no-repeat left/cover;
}

.navOpenPlay {
  animation: Play 1s steps(24) 1 forwards;
}

.navOpenPlayBack {
  animation: PlayBack 1s steps(24) 1 backwards;
}

@keyframes Play {
  0% {
    background-position: 0px;
  }

  100% {
    background-position: -1536px;
  }
}

@keyframes PlayBack {
  0% {
    background-position: -1536px;
  }

  100% {
    background-position: 0px;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="navOpen"></div>
0 голосов
/ 28 апреля 2020

Если вы хотите отменить анимацию только при выходе из нее до завершения анимации, анимация может быть связана с селектором css :hover:

#navOpen{
  width: 64px;
  height: 64px;
  /* reused the css-sprites because of laziness... */
  background: url('https://i.postimg.cc/hv0L4vsL/css-sprites.png') no-repeat left/cover; 
  transition: transform 2s;
}

#navOpen:hover{
  transform: rotate(90deg);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<div id="navOpen"></div>

Однако, если вы действительно хотите закончить sh всю анимацию перед реверсом, она немного более многословна. Основная причина в том, что вы должны проверять каждый раз, когда анимация заканчивается, если она все еще находится в правильном состоянии . При этом я имею в виду состояние , как если бы пользователь завис над вашим #navbar, и ему назначен класс navOpenPlay или navOpenPlayBack.

// Javascript accessor to use "onanimationend"
let nav = document.getElementById("navOpen")
// First of all, we need to keep track if an animation is running or not. 
// This helps us, to prevent interruption of an animation through adding/removing css classes before the animation finished.
// We stock this information in the variable `navIsReady`.
let navIsReady = true

// Define a function to change the state. 
// If play === true, we add animation for onMouseOver by adding the corresponding css classes
function changeState(play) {
  // Verify if another animation is currently running
  if (navIsReady === true) {
    navIsReady = false // indicate that an animation is running
    if (play) { // previously called on mouseOver
      $(nav).removeClass("navOpenPlayBack").addClass("navOpenPlay")
    } else { // previously called on mouseOut
      $(nav).removeClass("navOpenPlay").addClass("navOpenPlayBack")
    }
  }
}

// Define a callback when an animation ends. 
// The callback checks that the object is in the right state after finishing the animation
nav.onanimationend = function(event) {
  navIsReady = true // allow animations again
  // Check if the navigation is in the correct state after finishing the animation 
  if ($(nav).is(':hover') && (!$(nav).hasClass("navOpenPlay"))) {
    // False state. Change the state through a call
    changeState(true)
  } else if (!$(nav).is(':hover') && (!$(nav).hasClass("navOpenPlayBack"))) {
    // False state. Change the state through a call
    changeState(false)
  }
};

// Hook MouseOver and MouseOut events
$(nav).mouseover(function() {
  changeState(true)
});
$(nav).mouseout(function() {
  changeState(false)
});
#navOpen {
  width: 64px;
  height: 64px;
  background: url('https://i.postimg.cc/hv0L4vsL/css-sprites.png') no-repeat left/cover;
}

.navOpenPlay {
  animation: Play 1s steps(24) 1 forwards;
}

.navOpenPlayBack {
  animation: PlayBack 1s steps(24) 1 backwards;
}

@keyframes Play {
  0% {
    background-position: 0px;
  }
  100% {
    background-position: -1536px;
  }
}

@keyframes PlayBack {
  0% {
    background-position: -1536px;
  }
  100% {
    background-position: 0px;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<div id="navOpen"></div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...