'Animation will not run even after adding animation class to the element via addEventListener in React
I am trying to trigger a progress bar animation when a scroll eventlistener is triggered by adding the animation class when a scroll is detected. But it only runs when the page loads and does not run after that, when I scroll. The following are the JS and CSS files. Is there something wrong with the code or am I using setState wrongly?
.body2 {
background-color: #151515;
height: 700px;
}
.title2 {
font-size: 40px;
font-family: handwritten;
color: #d10100;
text-align: center;
padding-top: 100px;
grid-area: 1 / 1 / 2 / 2;
letter-spacing: 5px;
font-stretch: extra-condensed;
}
.titleback2 {
font-size: 90px;
font-family: ARCHIVO-bold;
-webkit-text-stroke-color: #212121;
-webkit-text-stroke-width: 3px;
color: #151515;
text-align: center;
padding-top: 75px;
grid-area: 1 / 1 / 2 / 2;
}
.bar{
background-color: #e3e3e3;
width: 400px;
height: 20px;
}
.bargrid {
margin: 200px;
height: 500px;
display: grid;
grid-template: 1fr 1fr 1fr/ 1fr 1fr;
justify-items: center;
}
.barlabel {
color: #e3e3e3;
font-family: cafe;
padding-bottom: 10px;
}
.progress{
background-color: #d10100;
background-image: linear-gradient(to right, #d10100 30%,#ff3231, #ff5f5e);
height: 20px;
position: relative;
bottom: 20px;
padding-left: 2px;
padding-right: 2px;
}
.loadpage {
animation: progressbar 2s normal;
}
@keyframes progressbar{
0% {width: 0%}
100% {width: 100%}
}
import React from "react";
import './Skills.css';
class Skills extends React.Component {
constructor(props){
super(props);
this.state = {
progress: 'progress',
}
this.changeState = this.changeState.bind(this)
}
changeState = () => {
this.setState({
progress: 'progress loadpage'
})
}
componentDidMount(){
window.addEventListener('scroll', this.changeState)
this.setState({
progress: 'progress'
})
}
render() {
return (
<div className="body2">
<div className="container">
<div className="titleback2">SKILLS</div>
<div className="title2">skills</div>
</div>
<div className="bargrid">
<div className="cell1">
<div className="barlabel">HTML</div>
<div className="bar" />
<div className={this.state.progress} />
</div>
<div className="cell2">
<div className="barlabel">CSS</div>
<div className="bar" />
<div className={this.state.progress} />
</div>
<div className="cell3">
<div className="barlabel">JAVASCRIPT</div>
<div className="bar" />
<div className={this.state.progress} />
</div>
<div className="cell4">
<div className="barlabel">REACT.JS</div>
<div className="bar" />
<div className={this.state.progress} />
</div>
<div className="cell5">
<div className="barlabel">FRAMER MOTION</div>
<div className="bar" />
<div className={this.state.progress} />
</div>
<div className="cell6">
<div className="barlabel">HTML</div>
<div className="bar" />
<div className={this.state.progress} />
</div>
</div>
</div>
);
}
}
export default Skills;
Solution 1:[1]
It can be handled simply by using the animationend event in JavaScript.
mdn document address. ( https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/animationend_event )
I'll show you the code sandbox address, so it might be helpful for reference.
Code sandbox address. ( https://codesandbox.io/s/react-playground-forked-yzmjrn?file=/index.js )
Skills.js
import React from "react";
import "./Skills.css";
class Skills extends React.Component {
constructor(props) {
super(props);
this.state = {
progress: "progress"
};
this.changeState = this.changeState.bind(this);
}
changeState = () => {
this.setState({
progress: "progress loadpage"
});
};
componentDidMount() {
window.addEventListener("scroll", () => {
console.log("scrolling...");
this.changeState();
});
this.setState({
progress: "progress"
});
// const animated = document.querySelector(".progress");
// animated.addEventListener("animationend", () => {
// console.log("Animation ended");
// this.setState({
// progress: "progress"
// });
// });
// I think this is better than above code.
document.addEventListener("animationend", (e) => {
// console.log(e);
console.log("Animation ended");
// remove loadpage classname
if (e.animationName === "progressbar") {
this.setState({
progress: "progress"
});
}
});
}
render() {
return (
<div className="body2">
<div className="container">
<div className="titleback2">SKILLS</div>
<div className="title2">skills</div>
</div>
<div className="bargrid">
<div className="cell1">
<div className="barlabel">HTML</div>
<div className="bar" />
<div className={this.state.progress} />
</div>
<div className="cell2">
<div className="barlabel">CSS</div>
<div className="bar" />
<div className={this.state.progress} />
</div>
<div className="cell3">
<div className="barlabel">JAVASCRIPT</div>
<div className="bar" />
<div className={this.state.progress} />
</div>
<div className="cell4">
<div className="barlabel">REACT.JS</div>
<div className="bar" />
<div className={this.state.progress} />
</div>
<div className="cell5">
<div className="barlabel">FRAMER MOTION</div>
<div className="bar" />
<div className={this.state.progress} />
</div>
<div className="cell6">
<div className="barlabel">HTML</div>
<div className="bar" />
<div className={this.state.progress} />
</div>
</div>
</div>
);
}
}
export default Skills;
It's not perfect, but I hope it helps?.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
