I want to create a script where my HTML-div is being animated everytime a key is pressed. Here is my code:
let square = document.querySelector("div")
document.addEventListener("keydown", function(e) {
square.style.animation = "shake 0.5s"
square.style.animationIterationCount = "infinite"
})
My problem is, if I exclude the last line where I set animation-iteration-count
to "infinite"
, it works once, and if I press the button again, it won't work anymore. But if I set it to "infinite", the animation won't stop. How can I set it so that I see the animation every time I press a button, but without having the animation all the time? Thanks for any suggestion!
CodePudding user response:
The point is to add an animationend Event to div
let square = document.querySelector("div.square");
document.addEventListener("keydown", function(e) {
square.classList.add('shake-square')
})
square.addEventListener("animationend", function(e) {
square.classList.remove('shake-square')
});
.square {
border: 1px solid black;
}
.shake-square {
animation: shake 0.5s;
}
@keyframes shake {
10%,
90% {
transform: translate3d(-1px, 0, 0);
}
20%,
80% {
transform: translate3d(2px, 0, 0);
}
30%,
50%,
70% {
transform: translate3d(-4px, 0, 0);
}
40%,
60% {
transform: translate3d(4px, 0, 0);
}
}
<div >
this is a square
</div>
This example will keep shaking until the keyup
event
If you only want to trigger shaking once on keydown
, modify keydown
event to
document.addEventListener("keydown", function (e) {
if (!e.repeat)
square.classList.add('shake-square')
})
CodePudding user response:
CSS animation
Properties
Let CSS do the heavy lifting when doing simple animation in the DOM. Add a ruleset in CSS with a class selector and all of the animation properties in it. This is the shorthand of all the animation properties, see example CSS for the long version:
.anim {
animation: shake 0.05s ease-in-out 0s infinite alternate forwards running;
}
Add the keyframes (see example CSS last ruleset @keyframes shake
)
JavaScript Event Handling
Bind the document
or window
to both "keydown"
and "keyup"
events and call the same event handler animate(e)
:
document.onkeydown = animate;
document.onkeyup = animate;
By defining an event handler using Event Object properties/bubbling and specifying elements and/or actions we can have granular control of user interaction, this paradigm is called event delegation. Here are the key parts of the event handler animate(e)
:
// Determining the current triggered with Event property `Event.type`
const eType = e.type;
// Dictate the action taken according to current event ("keydown/up")
switch(eType) {
/*
All animation is tied into the CSS ruleset `.anim {...}` so we just flip the
.anim class on/off
*/
case "keydown":
square.classList.add('anim');
break;
case "keyup":
square.classList.remove('anim');
break;
Click the snippet area to get focus first, then press any key (you can keep key pressed as well like the deprecated "keypress"
event)
document.onkeydown = animate;
document.onkeyup = animate;
function animate(e) {
const square = document.querySelector('div');
const eType = e.type;
switch(eType) {
case "keydown":
square.classList.add('anim');
break;
case "keyup":
square.classList.remove('anim');
break;
default:
break;
}
}
div {
width: 128px;
height: 128px;
margin: 50px auto;
border: 3px ridge blue;
}
.anim {
animation-name: shake;
animation-duration: 0.05s;
animation-timing-function: ease-in-out;
animation-delay: 0s;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-fill-mode: forwards;
animation-play-state: running;
}
@keyframes shake {
from {
transform: translateX(0px);
}
to {
transform: translateX(64px);
}
}
<div></div>