简体   繁体   English

为什么元素只有在计时器结束后才开始旋转

[英]why element starts rotating only after timer ends

here's a html p element.这是一个 html p 元素。 When clicked:点击时:

  1. background-color is changed to red than yellow背景颜色更改为red而不是yellow
  2. it starts to rotate using css transform, by setting the element class to refresh-start它使用 css 变换开始旋转,通过将元素 class 设置为refresh-start

This is done in the click handler onClickRefresh .这是在点击处理程序onClickRefresh中完成的。

However changes are reflected only after the timer is called, ends its operation and return.但是,只有调用timer 、结束其操作并返回后才会反映更改。 timer waits 5 sec (5000ms).计时器等待 5 秒(5000 毫秒)。

I would expect to see the changes immediately, before timer is called.我希望在调用计时器之前立即看到更改。 that is:那是:

  1. rotation starts immediately旋转立即开始
  2. 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" class="refresh-end" onclick="onClickRefresh(this)"/> text </p>

Your timer function is synchronous it blocks the next code until it is completely executed.您的timer function 是同步的,它会阻塞下一个代码,直到它完全执行。 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" class="refresh-end" onclick="onClickRefresh(this)"/> text </p>

Try using setTimeout尝试使用setTimeout

setTimeout(
  () => {    
    $(id).css("background-color","yellow");
  }, 
  5000
);

This code calls a function after 5000 milliseconds, that changes the background-color to yellow.此代码在 5000 毫秒后调用 function,将背景颜色更改为黄色。 The rest of your code is executed immediately.您的代码的 rest 会立即执行。

 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" class="refresh-end" onclick="onClickRefresh(this)"/> text </p>

TL;DR: Use setTimeout() : TL;DR:使用setTimeout()

    //remove the "`timer(5000);`" line and the timer function.
    setTimeout(() => {
      $(id).css("background-color","yellow");
    }, 5000)

Your problem is in the timer function.您的问题出在计时器 function 中。 HTML/JavaScript/CSS are single-threaded. HTML/JavaScript/CSS 是单线程的。 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.您的计时器 function 中有某种无限循环,尽管它在 5 秒后结束,但与此同时,一切都“滞后”了,CSS Z6F1C25ED1523962F1BBF9DEE9509 无法启动。 For this reason you have to use this syntax:因此,您必须使用以下语法:

setTimeout(() => {
    //code...
}, 5000 /*delay in milliseconds*/)

That's because the code below timer(5000) doesn't execute in 5 second cuz css("background-color", "yellow") execute synchronously.这是因为 timer(5000) 下面的代码不会在 5 秒内执行,因为 css("background-color", "yellow") 是同步执行的。 Which means JavaScript all put css effect immediately and just execute the timer and just run the timer in background.这意味着 JavaScript 都立即放置 css 效果,只需执行计时器并在后台运行计时器。 If you wanna change the background color from red to yellow in 5 second, you should use "setTimeout".如果你想在 5 秒内将背景颜色从红色变为黄色,你应该使用“setTimeout”。 It execute the call back function in it in the time you put.它会在您输入的时间内在其中执行回调 function。

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希望你能找到答案:D

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM