javascript - 在触发新动画之前完成一个 CSS 动画
问题描述
我正在尝试在悬停和取消悬停时创建运动图像。当鼠标悬停在图像上时,动画应该以一种方式流动,而当鼠标离开图像时,动画应该以另一种方式流动。
为此,我目前正在使用带有图像精灵的 css 动画。问题是,当鼠标在动画时间(1 秒)过去之前移动/离开图像时,图像会跳到下一个动画的开头,而不会完成上一个动画。
我尝试了各种方法来解决这个问题,但我似乎无法让它发挥作用(是的,这是我目前缺乏的技能)。有什么方法可以让动画始终在开始新动画之前完成?
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");
});
解决方案
如果您只是想在完成动画之前离开时反转动画,则可以将动画与 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>
但是,如果你真的想在倒车前完成整个动画,那就有点冗长了。主要原因是每次动画结束时您都必须验证它是否仍处于正确状态。因此,我指的状态好像用户悬停在您的上方#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>
推荐阅读
- autohotkey - Autohotkey - 在屏幕上的特定位置单击时发送键
- python - 如何修复'NoneType'对象在递归函数中没有属性'json'
- python - 向 Spacy 3.0 添加自定义语言并在其中训练管道
- c# - 水印图像尺寸很小并且在另一个图像中重复
- r - 如何将插图放置在 ggplot 上的确切位置并设置 geom_segment 的颜色?
- java - Java 拉绳在代码的早期部分工作正常以计算点数,但在显示游戏结束时不起作用
- node.js - 提交带有多个文本输入和图像的 React 表单
- python - Django db 2个外键之一不返回对象
- java - 在线程之间同步对象的最佳实践
- swift - 在 SwiftUI 中按值对 Json 数据进行分组