如何使动画暂停在悬停,但一旦鼠标离开动画继续



我已经尝试了几个解决方案,这是我得到的最接近的。但我仍然不满意它的结果,因为当鼠标离开元素时,元素会恢复到原来的旋转。这个想法是,如果你越过元素,即使鼠标离开元素,它也会触发动画。如果鼠标悬停在元素上,则播放动画并保持在0度,一旦鼠标离开,则播放另一个动画,并旋转回-8度。

const elements = document.getElementsByClassName('rotate_left');
for (let i = 0; i <= elements.length; i++) {
elements[i].addEventListener('animationend', function(e) {
elements[i].classList.remove('animated')
/*elements[i].classList.add('animatedback')*/
});
elements[i].addEventListener('mouseover', function(e) {
elements[i].classList.add('animated')
elements[i].classList.remove('animatedback')
});
}
.rotate_left {
-ms-transform: rotate(-8deg);
-webkit-transform: rotate(-8deg);
transform: rotate(-8deg);
transition-duration: 1s;
transition-delay: 0.25s;
}
.polaroid {
width: 280px;
height: 200px;
padding: 10px 15px 100px 15px;
border: 1px solid #BFBFBF;
border-radius: 2%;
background-color: white;
box-shadow: 10px 10px 5px #aaaaaa;
}
.polaroid:hover {
width: 280px;
height: 200px;
padding: 10px 15px -100px 15px;
border: 1px solid #BFBFBF;
border-radius: 2%;
background-color: white;
box-shadow: 10px 10px 5px #aaaaaa;
-ms-transform: rotate(0deg);
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
transition-duration: 1s;
transition-delay: 0.25s;
}
@keyframes animationBegining {
from {
-ms-transform: rotate(-8deg);
/* IE 9 */
-webkit-transform: rotate(-8deg);
/* Safari */
transform: rotate(-8deg);
}
to {
-ms-transform: rotate(0deg);
/* IE 9 */
-webkit-transform: rotate(0deg);
/* Safari */
transform: rotate(0deg);
}
}
@keyframes animatedBack {
form {
-ms-transform: rotate(0deg);
/* IE 9 */
-webkit-transform: rotate(0deg);
/* Safari */
transform: rotate(0deg);
}
to {
-ms-transform: rotate(-8deg);
/* IE 9 */
-webkit-transform: rotate(-8deg);
/* Safari */
transform: rotate(-8deg);
}
}
.animatedback {
animation: animatedBack 2s;
}
.animated {
animation: animationBegining 2s;
}
<div id="modalWrepper1" class="polaroid rotate_left">
<p class="caption">Just a basic explanation of the picture.</p>
</div>

非常感谢你的帮助。

当鼠标离开元素时,返回到初始旋转的平滑动画。

纯CSS解决方案(第二个动画主题为预防)

你不需要JS或任何花哨的类。transformtransition-duration就可以了。

让我们从HTML开始;这仍然是你的代码,但是简化了:

<div class="polaroid rotate_left">
<p>Just a basic explanation of the picture.</p>
</div>

现在,主要部分:CSS。因为你的卡牌默认旋转-8度,我们包含一个规则来实现:

.rotate_left {
transform: rotate(-8deg);
transition-duration: 1s;
transition-delay: 0.25s;
}

如果将.polaroid悬停在上方,它将旋转回0度。这意味着我们可以使用伪类:hover:

.polaroid:hover {
transform: rotate(0deg);
}

一旦将鼠标从.polaroid移开,:hover规则就不再适用。这意味着它将在1秒内恢复到以前的规则,在鼠标离开后0.25秒开始。

试一试:

.rotate_left {
transform: rotate(-8deg);
transition-duration: 1s;
transition-delay: 0.25s;
}
.polaroid:hover {
transform: rotate(0deg);
}
/* Demo only */
.polaroid {
border: 1px solid #bfbfbf;
border-radius: 2%;
padding: 10px 15px;
height: 200px;
width: 280px;
box-shadow: 10px 10px 5px #aaa;
}
<div class="polaroid rotate_left">
<p>Just a basic explanation of the picture.</p>
</div>

阻止第二个动画被停止

为了防止恢复被停止,需要一点JS。

首先声明一些常量:

const card = document.querySelector('.rotate_left');
const duration = 1000; // Duration of animation, in milliseconds.
const delay = 250; // Delay before animation, in milliseconds.
const keyframes = [
{ transform: 'rotate(-8deg)' },
{ transform: 'rotate(0deg)' },
];
const options = {
duration, delay,
fill: 'forwards'
};
然后创建一个处理程序:
const handler = () => {
// New mouse over & leave should not mess with current animation.
if (card.classList.contains('rotating')) {
return;
}

// Let ourselves know that an animation is playing.
card.classList.add('rotating');

let animation;

if (card.classList.contains('not_rotated')) {
// Rotated to 0 degree, reverting.
animation = card.animate([...keyframes].reverse(), options);
} else {
animation = card.animate(keyframes, options);
}

// Make sure we clean after ourselves after animation.
animation.finished.then(() => {
card.classList.remove('rotating');
card.classList.toggle('not_rotated');
});
};

添加它作为'mouseover'/'mouseleave'的事件处理程序,我们完成了:

card.addEventListener('mouseover', handler);
card.addEventListener('mouseleave', handler);

试一试:

const card = document.querySelector('.rotate_left');
const duration = 1000; // Duration of animation, in milliseconds.
const delay = 250; // Delay before animation, in milliseconds.
const keyframes = [
{ transform: 'rotate(-8deg)' },
{ transform: 'rotate(0deg)' },
];
const options = {
duration, delay,
fill: 'forwards'
};
const handler = () => {
if (card.classList.contains('rotating')) {
return;
}

card.classList.add('rotating');

let animation;

if (card.classList.contains('not_rotated')) {
animation = card.animate([...keyframes].reverse(), options);
} else {
animation = card.animate(keyframes, options);
}

animation.finished.then(() => {
card.classList.remove('rotating');
card.classList.toggle('not_rotated');
});
};
card.addEventListener('mouseover', handler);
card.addEventListener('mouseleave', handler);
.rotate_left {
transform: rotate(-8deg);
}
/* Demo only */
.polaroid {
border: 1px solid #bfbfbf;
border-radius: 2%;
padding: 10px 15px;
height: 200px;
width: 280px;
box-shadow: 10px 10px 5px #aaa;
}
<div class="polaroid rotate_left">
<p>Just a basic explanation of the picture.</p>
</div>

TLDR我想这就是你想要的:

const rotateForwardAnimationName = 'rotate-forward';
const rotateBackwardAnimationName = 'rotate-backward';
const states = {
forward: 'forward',
backward: 'backward',
rotatingForward: 'rotatingForward',
rotatingBackward: 'rotatingBackward',
};
const elements = document.getElementsByClassName('polaroid');
const stateMap = new Map();
for (const element of elements) {
stateMap.set(element, states.backward);
element.addEventListener('animationstart', (e) => {
if (e.animationName === rotateForwardAnimationName)
stateMap.set(element, states.rotatingForward);
if (e.animationName === rotateBackwardAnimationName)
stateMap.set(element, states.rotatingBackward);
onStateUpdate(element);
});
element.addEventListener('animationend', (e) => {
if (e.animationName === rotateForwardAnimationName)
stateMap.set(element, states.forward);
if (e.animationName === rotateBackwardAnimationName)
stateMap.set(element, states.backward);
onStateUpdate(element);
});
element.addEventListener('mouseenter', () =>
onStateUpdate(element)
);
element.addEventListener('mouseleave', () =>
onStateUpdate(element)
);
}
function onStateUpdate(element) {
const hovered = element.matches(':hover');
const state = stateMap.get(element);
if (state === states.forward && !hovered) rotateBackward(element);
if (state === states.backward && hovered) rotateForward(element);
}
function rotateBackward(element) {
element.style.animation = rotateBackwardAnimationName + ' 2s forwards';
}
function rotateForward(element) {
element.style.animation = rotateForwardAnimationName + ' 2s forwards';
}
.polaroid {
width: 280px;
height: 200px;
padding: 10px 15px 100px 15px;
border: 1px solid #bfbfbf;
border-radius: 2%;
background-color: white;
box-shadow: 10px 10px 5px #aaaaaa;
transform: rotate(-8deg);
}
@keyframes rotate-forward {
from {
transform: rotate(-8deg);
}
to {
transform: rotate(0deg);
}
}
@keyframes rotate-backward {
from {
transform: rotate(0deg);
}
to {
transform: rotate(-8deg);
}
}
<div class="polaroid">
<p class="caption">Just a basic explanation of the picture.</p>
</div>
<div class="polaroid">
<p class="caption">Just a basic explanation of the picture.</p>
</div>

Stackblitz Typescript示例:https://stackblitz.com/edit/typescript-bkyk66?file=index.ts


您正在寻找比CSS提供的更细粒度的动画控制。这意味着你必须跟踪你自己的动画状态。

在这种情况下,有两种状态:动画状态和悬停状态。

动画状态有四个互斥的值:向后、向前、向后旋转和向前旋转。

悬停状态只能为真或假。

我发现制作真值表有助于辨别在所有这些状态组合中会发生什么。我相信这些是你想要的行动,但我不确定:

tbody> <<tr>向后
动画状态 悬停状态 动作
转发任何行动
向前False开始向后旋转
反向True开始正向旋转
任何行动
旋转向前任何行动
旋转向前任何行动
向后旋转任何行动
向后旋转False无动作

相关内容

  • 没有找到相关文章

最新更新