【问题标题】:Proper timeout for JavascriptJavascript的正确超时
【发布时间】:2021-01-31 01:59:15
【问题描述】:

我知道 CSS 过渡不适用于 auto 关键字,所以如果我想应用 transition: left 2s, right 2s; 必须左右(比如说)0 100.

我有一个脚本,它可能会向左或向右改变对象的位置,但如果 left 设置为 0(它必须是 auto),我无法设置 right: 100

所以我想出了这个解决方案。

function moveObject(direction) {
    direction ? myobject.style.right = 0 : myobject.style.left = 0;    //same position as auto but can be transitioned
    direction ? myobject.style.right = "50vw" : myobject.style.left = "50vw";    //actual transition
}

function resetObject() {
    myObject.style.left = myObject.style.right = "auto";   //now I can move to either right or left again
    //I don't need an animation on reset
}
#myobject {
    position: absolute;
    left: auto;
    right: auto;
    
    /*width, height...*/
}
<div id="myObject"></div>

这不起作用(对0 的分配被完全忽略)。

所以我提出了这个解决方案(与上面相同,但使用setTimeout(..., 0);

function moveObject(direction) {
    direction ? myobject.style.right = 0 : myobject.style.left = 0;

    setTimeout(function() {
        direction ? myobject.style.right = "50vw" : myobject.style.left = "50vw";    //this is executed async
    }, 0);
}

function resetObject() {
    myObject.style.left = myObject.style.right = "auto";
}
#myobject {
    position: absolute;
    left: auto;
    right: auto;
    
    /*width, height...*/
}
<div id="myObject"></div>

这改善了结果,但有时(似乎完全随机,但在小屏幕上更频繁),过渡仍然没有发生。

我想这是因为有时异步函数执行得太快,所以我尝试将延迟增加到10ms,但有时问题仍然存在(不太频繁)。

现在,我可以进一步提高价值,但是:

  • 我永远无法确定该错误迟早不会发生,也许是在更快的设备上(除非我将超时设置为一个非常大的数字)
  • 我不能将超时设置为非常大的数字,因为我希望它不易察觉

那么,有没有最低数量可以保证成功输出?

如果不是,怎么能达到同样的效果?

【问题讨论】:

标签: javascript html css function settimeout


【解决方案1】:

正如@Akxe 建议的那样,解决方案是重排页面。换句话说,浏览器会同时刷新 DOM 的多个更改。这会稍微加快页面速度,但会导致一些问题,例如我所描述的问题 (further information here)

正如here 建议的那样,解决方案是这样一个函数:

function reflow() {    //this will be called between the two elements
    void(document.documentElement.offsetWidth);
}

function moveObject(direction) {
    direction ? myobject.style.right = 0 : myobject.style.left = 0;
    reflow();   //the line above is now flushed
    direction ? myobject.style.right = "50vw" : myobject.style.left = "50vw";
}

function resetObject() {
    myObject.style.left = myObject.style.right = "auto";
}
#myobject {
    position: absolute;
    left: auto;
    right: auto;
    
    /*width, height...*/
}
<div id="myObject"></div>

即使不使用void,该功能实际上也对我有用,但我更喜欢保留它,因为在referenced question 中有人指出它对他不起作用,而且为了更清晰。

This 也可能有用:它是导致页面重排的所有内容的(非官方)列表。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-09-28
    • 2011-08-23
    • 1970-01-01
    • 1970-01-01
    • 2013-10-12
    • 2011-01-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多