here's a html p element. When clicked:
- background-color is changed to
red
thanyellow
- it starts to rotate using css transform, by setting the element class to
refresh-start
This is done in the click handler onClickRefresh
.
However changes are reflected only after the timer
is called, ends its operation and return. timer waits 5 sec (5000ms).
I would expect to see the changes immediately, before timer is called. that is:
- rotation starts immediately
- color changes to red than yellow
this is not happening. How does it make sense?
function onClickRefresh(el){
//jquery selector
let id = "#" el.id;
//read class
const co = (id)=>{ return $(id).attr("class")}
//current class
console.log("class before:", co(id));
//setting class - start rotating
el.className = "refresh-start";
console.log("class after:", co(id));
//temp color
$(id).css("background-color","red");
timer(5000);
$(id).css("background-color","yellow");
}
function timer(ms){
const d1 = new Date();
let cont = true;
while (cont){
let d2 = new Date();
cont = (d2-d1 >= ms ? false : true);
}
}
@keyframes rotate {
from {transform: rotate(0deg)}
to {transform: rotate(360deg)}
}
.refresh-start {
animation-name: rotate;
animation-duration: 1.5s;
animation-iteration-count: infinite;
animation-timing-function: linear;
animation-play-state: running;
}
.refresh-end{
animation-play-state: paused;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<p id="refreshNRList1" onclick="onClickRefresh(this)"/>
text
</p>
CodePudding user response:
Your timer
function is synchronous it blocks the next code until it is completely executed. try asynchronous timer
async function onClickRefresh(el) {
//jquery selector
let id = "#" el.id;
//read class
const co = (id) => {
return $(id).attr("class");
};
//current class
console.log("class before:", co(id));
//setting class - start rotating
el.className = "refresh-start";
console.log("class after:", co(id));
//temp color
$(id).css("background-color", "red");
await timer(5000);
$(id).css("background-color", "yellow");
}
async function timer(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
@keyframes rotate {
from {transform: rotate(0deg)}
to {transform: rotate(360deg)}
}
.refresh-start {
animation-name: rotate;
animation-duration: 1.5s;
animation-iteration-count: infinite;
animation-timing-function: linear;
animation-play-state: running;
}
.refresh-end{
animation-play-state: paused;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<p id="refreshNRList1" onclick="onClickRefresh(this)"/>
text
</p>
CodePudding user response:
Try using setTimeout
setTimeout(
() => {
$(id).css("background-color","yellow");
},
5000
);
This code calls a function after 5000 milliseconds, that changes the background-color to yellow. The rest of your code is executed immediately.
function onClickRefresh(el){
//jquery selector
let id = "#" el.id;
//read class
const co = (id)=>{ return $(id).attr("class")}
//current class
console.log("class before:", co(id));
//setting class - start rotating
el.className = "refresh-start";
console.log("class after:", co(id));
//temp color
$(id).css("background-color","red");
setTimeout(
() => {
$(id).css("background-color","yellow");
},
5000
);
}
@keyframes rotate {
from {transform: rotate(0deg)}
to {transform: rotate(360deg)}
}
.refresh-start {
animation-name: rotate;
animation-duration: 1.5s;
animation-iteration-count: infinite;
animation-timing-function: linear;
animation-play-state: running;
}
.refresh-end{
animation-play-state: paused;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<p id="refreshNRList1" onclick="onClickRefresh(this)"/>
text
</p>
CodePudding user response:
TL;DR: Use setTimeout()
:
//remove the "`timer(5000);`" line and the timer function.
setTimeout(() => {
$(id).css("background-color","yellow");
}, 5000)
Your problem is in the timer function. HTML/JavaScript/CSS are single-threaded. It means, that if you make something in an infinite loop, everything will stop. You had some kind of infinite loop in your timer function, though it ended at the end on 5 seconds, but in the meanwhile, everything was 'lagged' and the CSS animation couldn't start. For this reason you have to use this syntax:
setTimeout(() => {
//code...
}, 5000 /*delay in milliseconds*/)
CodePudding user response:
That's because the code below timer(5000) doesn't execute in 5 second cuz css("background-color", "yellow") execute synchronously. Which means JavaScript all put css effect immediately and just execute the timer and just run the timer in background. If you wanna change the background color from red to yellow in 5 second, you should use "setTimeout". It execute the call back function in it in the time you put.
Here is my solution.
function onClickRefresh(el){
let id = "#" el.id;
const co = (id)=>{ return $(id).attr("class")}
el.className = "refresh-start";
$(id).css("background-color","red");
setTimeout(() => {
$(id).css("background-color","yellow");
}, 5000);
}
I hope you find an answer :D