为什么当持续时间减少 JavaScript 时动画不完成其路径
Why animation don't complete its path when duration is decreased by JavaScript
我有一个动画,它的 duration
每次 black 跳跃(使用 space)超过 red,后续跳转减少 duration
.
效果很好
但是时间减少了一定时间后,比如说减少到4s
,3.9s
,3.8s
...之后,动画就不是从最右端开始了这应该是。因为在 @keyframes animateVillan
中决定了 path(110vw)
有没有我做错了什么,首先认为这是一个小故障,并且决定仅在 red 达到小于 10 时才更改持续时间并尝试以下部分
if (ourVillanFigXValue < 10) {
ourVillanFig.style.animationDuration = ourVillanAnimeDuration - 0.1 + "s";
}
但这并没有解决问题,red
没有完全追踪路径
Sorry have to jump a little, 4 or 5 jumps only to see the error plz
let ourHeroFig = document.getElementById("ourHero");
let ourVillanFig = document.getElementById("obstacleBar");
let gameScoreDigits = document.getElementById("gameScoreDigits");
let valueXCoordinate = "";
let obstacleBarCrossed = true;
document.body.addEventListener('keydown', function(e) {
let ourHeroFigXValue = parseInt(getComputedStyle(ourHeroFig).getPropertyValue('left'));
let ourHeroFigYValue = parseInt(getComputedStyle(ourHeroFig).getPropertyValue('bottom'));
if (e.code === "ArrowRight") {
valueXCoordinate = ourHeroFigXValue + 100;
} else if (e.code === "KeyA" || e.code === "ArrowLeft") {
if (ourHeroFigXValue > ourHeroFig.offsetWidth + 90) {
valueXCoordinate = ourHeroFigXValue - 100;
} else {
valueXCoordinate = 0;
}
} else if (e.code === "Space") {
ourHeroFig.classList.add("animateHero");
setTimeout(function() {
ourHeroFig.classList.remove("animateHero");
}, 700)
}
changePosition();
})
function changePosition() {
ourHeroFig.style.left = valueXCoordinate + 'px'
}
let delayInAnimeSub = ""
setInterval(
function() {
let ourHeroFigXValue = parseInt(getComputedStyle(ourHeroFig).getPropertyValue('left'));
let ourHeroFigYValue = parseInt(getComputedStyle(ourHeroFig).getPropertyValue('bottom'));
let ourVillanFigXValue = parseInt(getComputedStyle(ourVillanFig).getPropertyValue('left'));
let ourVillanFigYValue = parseInt(getComputedStyle(ourVillanFig).getPropertyValue('bottom'));
let gameOverValueX = Math.abs(ourVillanFigXValue - ourHeroFigXValue);
let gameOverValueY = Math.abs(ourVillanFigYValue - ourHeroFigYValue);
if (ourVillanFigXValue < 10) {
ourVillanFig.style.animationDuration = ourVillanAnimeDuration - 0.3 + "s";
}
if (gameOverValueX < ourVillanFig.offsetWidth && gameOverValueY < ourVillanFig.offsetHeight) {
console.log("yes touched");
ourVillanFig.classList.remove("animateVillan");
obstacleBarCrossed = false;
} else if (obstacleBarCrossed && gameOverValueX < ourVillanFig.offsetWidth) {
ourVillanAnimeDuration = parseFloat(getComputedStyle(ourVillanFig).getPropertyValue('animation-duration'));
console.log(ourVillanFigXValue < 0, ourVillanAnimeDuration)
if (ourVillanAnimeDuration <= 2) {
ourVillanAnimeDuration = 2
}
}
// console.log(gameOverValueX,gameOverValueY)
}, 10);
#ourHero {
width: 20px;
height: 180px;
background-color: black;
position: fixed;
bottom: 0;
left: 0;
transition: 0.1s;
}
.animateHero {
animation: animateHero 0.7s linear;
}
@keyframes animateHero {
0% {
bottom: 0;
}
50% {
bottom: 350px;
}
100% {
bottom: 0;
}
}
#obstacleBar {
width: 20px;
height: 180px;
background-color: red;
position: fixed;
bottom: 0;
left: 50vw;
}
.animateVillan {
animation: animateVillan 5s linear infinite;
}
@keyframes animateVillan {
0% {
left: 110vw;
}
100% {
left: 0;
}
}
<div id="ourHero"></div>
<div id="obstacleBar" class="animateVillan"></div>
提前感谢您的帮助
首先让红色的东西从最右边开始,所以将 left: 50vw;
更改为 left: 110vw;
之类的东西。此外,不是无限动画,而是在红色离开屏幕后删除 animateVillan
class 然后重新添加它。可以通过使用 animationend
事件处理程序来完成:
ourVillanFig.addEventListener('animationend', () => {
ourVillanFig.classList.remove('animateVillan')
ourVillanFig.clientHeight // just to cause a reflow
ourVillanFig.classList.add('animateVillan')
})
或者可能通过检查它的 x 位置,看看它什么时候出来。
这是结果。它似乎工作正常,没有任何故障:
编辑: 要使红色在接触黑色时停在原处,您可以进行以下 css class:
.pauseVillan {
animation-play-state: paused;
}
然后当红色接触时只需添加 pauseVillan
class 即可:
ourVillanFig.classList.add('pauseVillan')
这是更新后的代码段:
let ourHeroFig = document.getElementById('ourHero')
let ourVillanFig = document.getElementById('obstacleBar')
let gameScoreDigits = document.getElementById('gameScoreDigits')
let valueXCoordinate = ''
let obstacleBarCrossed = true
document.body.addEventListener('keydown', function(e) {
let ourHeroFigXValue = parseInt(
getComputedStyle(ourHeroFig).getPropertyValue('left')
)
let ourHeroFigYValue = parseInt(
getComputedStyle(ourHeroFig).getPropertyValue('bottom')
)
if (e.code === 'ArrowRight') {
valueXCoordinate = ourHeroFigXValue + 100
} else if (e.code === 'KeyA' || e.code === 'ArrowLeft') {
if (ourHeroFigXValue > ourHeroFig.offsetWidth + 90) {
valueXCoordinate = ourHeroFigXValue - 100
} else {
valueXCoordinate = 0
}
} else if (e.code === 'Space') {
ourHeroFig.classList.add('animateHero')
setTimeout(function() {
ourHeroFig.classList.remove('animateHero')
}, 700)
}
changePosition()
})
ourVillanFig.addEventListener('animationend', () => {
ourVillanFig.classList.remove('animateVillan')
ourVillanFig.clientHeight // just to cause a reflow
ourVillanFig.classList.add('animateVillan')
})
function changePosition() {
ourHeroFig.style.left = valueXCoordinate + 'px'
}
let delayInAnimeSub = ''
setInterval(function() {
let ourHeroFigXValue = parseInt(
getComputedStyle(ourHeroFig).getPropertyValue('left')
)
let ourHeroFigYValue = parseInt(
getComputedStyle(ourHeroFig).getPropertyValue('bottom')
)
let ourVillanFigXValue = parseInt(
getComputedStyle(ourVillanFig).getPropertyValue('left')
)
let ourVillanFigYValue = parseInt(
getComputedStyle(ourVillanFig).getPropertyValue('bottom')
)
let gameOverValueX = Math.abs(ourVillanFigXValue - ourHeroFigXValue)
let gameOverValueY = Math.abs(ourVillanFigYValue - ourHeroFigYValue)
if (ourVillanFigXValue < 10) {
ourVillanFig.style.animationDuration =
ourVillanAnimeDuration - 0.3 + 's'
}
if (
gameOverValueX < ourVillanFig.offsetWidth &&
gameOverValueY < ourVillanFig.offsetHeight
) {
console.log('yes touched')
ourVillanFig.classList.add('pauseVillan')
obstacleBarCrossed = false
} else if (
obstacleBarCrossed &&
gameOverValueX < ourVillanFig.offsetWidth
) {
ourVillanAnimeDuration = parseFloat(
getComputedStyle(ourVillanFig).getPropertyValue('animation-duration')
)
console.log(ourVillanFigXValue < 0, ourVillanAnimeDuration)
if (ourVillanAnimeDuration <= 2) {
ourVillanAnimeDuration = 2
}
}
// console.log(gameOverValueX,gameOverValueY)
}, 10)
#ourHero {
width: 20px;
height: 180px;
background-color: black;
position: fixed;
bottom: 0;
left: 0;
transition: 0.1s;
}
.animateHero {
animation: animateHero 0.7s linear;
}
@keyframes animateHero {
0% {
bottom: 0;
}
50% {
bottom: 350px;
}
100% {
bottom: 0;
}
}
#obstacleBar {
width: 20px;
height: 180px;
background-color: red;
position: fixed;
bottom: 0;
left: 110vw;
}
.animateVillan {
animation: animateVillan 4s linear;
}
.pauseVillan {
animation-play-state: paused;
}
@keyframes animateVillan {
0% {
left: 110vw;
}
100% {
left: 0;
}
}
<div id="ourHero"></div>
<div id="obstacleBar" class="animateVillan"></div>
我有一个动画,它的 duration
每次 black 跳跃(使用 space)超过 red,后续跳转减少 duration
.
但是时间减少了一定时间后,比如说减少到4s
,3.9s
,3.8s
...之后,动画就不是从最右端开始了这应该是。因为在 @keyframes animateVillan
有没有我做错了什么,首先认为这是一个小故障,并且决定仅在 red 达到小于 10 时才更改持续时间并尝试以下部分
if (ourVillanFigXValue < 10) {
ourVillanFig.style.animationDuration = ourVillanAnimeDuration - 0.1 + "s";
}
但这并没有解决问题,red
没有完全追踪路径Sorry have to jump a little, 4 or 5 jumps only to see the error plz
let ourHeroFig = document.getElementById("ourHero");
let ourVillanFig = document.getElementById("obstacleBar");
let gameScoreDigits = document.getElementById("gameScoreDigits");
let valueXCoordinate = "";
let obstacleBarCrossed = true;
document.body.addEventListener('keydown', function(e) {
let ourHeroFigXValue = parseInt(getComputedStyle(ourHeroFig).getPropertyValue('left'));
let ourHeroFigYValue = parseInt(getComputedStyle(ourHeroFig).getPropertyValue('bottom'));
if (e.code === "ArrowRight") {
valueXCoordinate = ourHeroFigXValue + 100;
} else if (e.code === "KeyA" || e.code === "ArrowLeft") {
if (ourHeroFigXValue > ourHeroFig.offsetWidth + 90) {
valueXCoordinate = ourHeroFigXValue - 100;
} else {
valueXCoordinate = 0;
}
} else if (e.code === "Space") {
ourHeroFig.classList.add("animateHero");
setTimeout(function() {
ourHeroFig.classList.remove("animateHero");
}, 700)
}
changePosition();
})
function changePosition() {
ourHeroFig.style.left = valueXCoordinate + 'px'
}
let delayInAnimeSub = ""
setInterval(
function() {
let ourHeroFigXValue = parseInt(getComputedStyle(ourHeroFig).getPropertyValue('left'));
let ourHeroFigYValue = parseInt(getComputedStyle(ourHeroFig).getPropertyValue('bottom'));
let ourVillanFigXValue = parseInt(getComputedStyle(ourVillanFig).getPropertyValue('left'));
let ourVillanFigYValue = parseInt(getComputedStyle(ourVillanFig).getPropertyValue('bottom'));
let gameOverValueX = Math.abs(ourVillanFigXValue - ourHeroFigXValue);
let gameOverValueY = Math.abs(ourVillanFigYValue - ourHeroFigYValue);
if (ourVillanFigXValue < 10) {
ourVillanFig.style.animationDuration = ourVillanAnimeDuration - 0.3 + "s";
}
if (gameOverValueX < ourVillanFig.offsetWidth && gameOverValueY < ourVillanFig.offsetHeight) {
console.log("yes touched");
ourVillanFig.classList.remove("animateVillan");
obstacleBarCrossed = false;
} else if (obstacleBarCrossed && gameOverValueX < ourVillanFig.offsetWidth) {
ourVillanAnimeDuration = parseFloat(getComputedStyle(ourVillanFig).getPropertyValue('animation-duration'));
console.log(ourVillanFigXValue < 0, ourVillanAnimeDuration)
if (ourVillanAnimeDuration <= 2) {
ourVillanAnimeDuration = 2
}
}
// console.log(gameOverValueX,gameOverValueY)
}, 10);
#ourHero {
width: 20px;
height: 180px;
background-color: black;
position: fixed;
bottom: 0;
left: 0;
transition: 0.1s;
}
.animateHero {
animation: animateHero 0.7s linear;
}
@keyframes animateHero {
0% {
bottom: 0;
}
50% {
bottom: 350px;
}
100% {
bottom: 0;
}
}
#obstacleBar {
width: 20px;
height: 180px;
background-color: red;
position: fixed;
bottom: 0;
left: 50vw;
}
.animateVillan {
animation: animateVillan 5s linear infinite;
}
@keyframes animateVillan {
0% {
left: 110vw;
}
100% {
left: 0;
}
}
<div id="ourHero"></div>
<div id="obstacleBar" class="animateVillan"></div>
提前感谢您的帮助
首先让红色的东西从最右边开始,所以将 left: 50vw;
更改为 left: 110vw;
之类的东西。此外,不是无限动画,而是在红色离开屏幕后删除 animateVillan
class 然后重新添加它。可以通过使用 animationend
事件处理程序来完成:
ourVillanFig.addEventListener('animationend', () => {
ourVillanFig.classList.remove('animateVillan')
ourVillanFig.clientHeight // just to cause a reflow
ourVillanFig.classList.add('animateVillan')
})
或者可能通过检查它的 x 位置,看看它什么时候出来。
这是结果。它似乎工作正常,没有任何故障:
编辑: 要使红色在接触黑色时停在原处,您可以进行以下 css class:
.pauseVillan {
animation-play-state: paused;
}
然后当红色接触时只需添加 pauseVillan
class 即可:
ourVillanFig.classList.add('pauseVillan')
这是更新后的代码段:
let ourHeroFig = document.getElementById('ourHero')
let ourVillanFig = document.getElementById('obstacleBar')
let gameScoreDigits = document.getElementById('gameScoreDigits')
let valueXCoordinate = ''
let obstacleBarCrossed = true
document.body.addEventListener('keydown', function(e) {
let ourHeroFigXValue = parseInt(
getComputedStyle(ourHeroFig).getPropertyValue('left')
)
let ourHeroFigYValue = parseInt(
getComputedStyle(ourHeroFig).getPropertyValue('bottom')
)
if (e.code === 'ArrowRight') {
valueXCoordinate = ourHeroFigXValue + 100
} else if (e.code === 'KeyA' || e.code === 'ArrowLeft') {
if (ourHeroFigXValue > ourHeroFig.offsetWidth + 90) {
valueXCoordinate = ourHeroFigXValue - 100
} else {
valueXCoordinate = 0
}
} else if (e.code === 'Space') {
ourHeroFig.classList.add('animateHero')
setTimeout(function() {
ourHeroFig.classList.remove('animateHero')
}, 700)
}
changePosition()
})
ourVillanFig.addEventListener('animationend', () => {
ourVillanFig.classList.remove('animateVillan')
ourVillanFig.clientHeight // just to cause a reflow
ourVillanFig.classList.add('animateVillan')
})
function changePosition() {
ourHeroFig.style.left = valueXCoordinate + 'px'
}
let delayInAnimeSub = ''
setInterval(function() {
let ourHeroFigXValue = parseInt(
getComputedStyle(ourHeroFig).getPropertyValue('left')
)
let ourHeroFigYValue = parseInt(
getComputedStyle(ourHeroFig).getPropertyValue('bottom')
)
let ourVillanFigXValue = parseInt(
getComputedStyle(ourVillanFig).getPropertyValue('left')
)
let ourVillanFigYValue = parseInt(
getComputedStyle(ourVillanFig).getPropertyValue('bottom')
)
let gameOverValueX = Math.abs(ourVillanFigXValue - ourHeroFigXValue)
let gameOverValueY = Math.abs(ourVillanFigYValue - ourHeroFigYValue)
if (ourVillanFigXValue < 10) {
ourVillanFig.style.animationDuration =
ourVillanAnimeDuration - 0.3 + 's'
}
if (
gameOverValueX < ourVillanFig.offsetWidth &&
gameOverValueY < ourVillanFig.offsetHeight
) {
console.log('yes touched')
ourVillanFig.classList.add('pauseVillan')
obstacleBarCrossed = false
} else if (
obstacleBarCrossed &&
gameOverValueX < ourVillanFig.offsetWidth
) {
ourVillanAnimeDuration = parseFloat(
getComputedStyle(ourVillanFig).getPropertyValue('animation-duration')
)
console.log(ourVillanFigXValue < 0, ourVillanAnimeDuration)
if (ourVillanAnimeDuration <= 2) {
ourVillanAnimeDuration = 2
}
}
// console.log(gameOverValueX,gameOverValueY)
}, 10)
#ourHero {
width: 20px;
height: 180px;
background-color: black;
position: fixed;
bottom: 0;
left: 0;
transition: 0.1s;
}
.animateHero {
animation: animateHero 0.7s linear;
}
@keyframes animateHero {
0% {
bottom: 0;
}
50% {
bottom: 350px;
}
100% {
bottom: 0;
}
}
#obstacleBar {
width: 20px;
height: 180px;
background-color: red;
position: fixed;
bottom: 0;
left: 110vw;
}
.animateVillan {
animation: animateVillan 4s linear;
}
.pauseVillan {
animation-play-state: paused;
}
@keyframes animateVillan {
0% {
left: 110vw;
}
100% {
left: 0;
}
}
<div id="ourHero"></div>
<div id="obstacleBar" class="animateVillan"></div>