Javascript 创建元素后立即触发转换

Javascript 创建元素后立即触发转换,javascript,css,transition,race-condition,Javascript,Css,Transition,Race Condition,我试图创建一个动作,其中创建了一个div,并立即向上“浮动”,直到它离开屏幕 为了实现这一点,我尝试使用CSS,它将完全由JavaScript驱动(由于我的用例中的限制) 当我创建一个元素,为其指定转换样式属性,然后立即尝试通过更改样式(top)来启动转换时,就会出现问题 似乎出现了一个计时问题,top样式更改在转换可用之前触发,因此只是立即将我的div移出屏幕,而不是实际执行转换 下面是一个简化的示例: var defaultHeight = 50, iCount = 0,

我试图创建一个动作,其中创建了一个div,并立即向上“浮动”,直到它离开屏幕

为了实现这一点,我尝试使用CSS,它将完全由JavaScript驱动(由于我的用例中的限制)

当我创建一个元素,为其指定转换样式属性,然后立即尝试通过更改样式(
top
)来启动转换时,就会出现问题

似乎出现了一个计时问题,
top
样式更改在转换可用之前触发,因此只是立即将我的div移出屏幕,而不是实际执行转换

下面是一个简化的示例:

var
    defaultHeight = 50,
    iCount = 0,
    aColors = ['red', 'orange', 'yellow', 'green', 'blue', 'purple'];

function createBlock() {
    var testdiv = document.createElement('div');
    testdiv.className = 'testdiv';
    document.body.appendChild(testdiv);
    testdiv.style.left = '50%';
    testdiv.style.backgroundColor = aColors[iCount % aColors.length];
    testdiv.style.width = defaultHeight + 'px';
    testdiv.style.height = defaultHeight + 'px';
    testdiv.style.fontSize = '30px';
    testdiv.style.textAlign = 'center';
    testdiv.innerHTML = iCount;
    testdiv.style.top = '500px';
    testdiv.style.position = 'absolute';
    iCount++;
    return testdiv;
}

document.getElementById('go').onclick = function() {
    var testdiv = createBlock();

    testdiv.style.transition = "top 2.0s linear 0s";

    setTimeout(function() {
        testdiv.style.top = (defaultHeight*-2) + 'px';
    }, 0); // <- change this to a higher value to see the transition always occur
};
var
默认高度=50,
i计数=0,
A颜色=[‘红色’、‘橙色’、‘黄色’、‘绿色’、‘蓝色’、‘紫色’];
函数createBlock(){
var testdiv=document.createElement('div');
testdiv.className='testdiv';
document.body.appendChild(testdiv);
testdiv.style.left='50%';
testdiv.style.backgroundColor=aColors[i计数%aColors.length];
testdiv.style.width=defaultHeight+'px';
testdiv.style.height=defaultHeight+'px';
testdiv.style.fontSize='30px';
testdiv.style.textAlign='center';
testdiv.innerHTML=iCount;
testdiv.style.top='500px';
testdiv.style.position='absolute';
iCount++;
返回testdiv;
}
document.getElementById('go')。onclick=function(){
var testdiv=createBlock();
testdiv.style.transition=“top 2.0s线性0s”;
setTimeout(函数(){
testdiv.style.top=(defaultHeight*-2)+“px”;

},0);//另一种方法是使用
动画

如果您想使用javascript动态创建
关键帧
,下面是一篇不错的帖子,展示了:

var
默认高度=50,
i计数=0,
A颜色=[‘红色’、‘橙色’、‘黄色’、‘绿色’、‘蓝色’、‘紫色’];
函数createBlock(){
var testdiv=document.createElement('div');
testdiv.className='testdiv';
document.body.appendChild(testdiv);
testdiv.style.left='50%';
testdiv.style.backgroundColor=aColors[i计数%aColors.length];
testdiv.style.width=defaultHeight+'px';
testdiv.style.height=defaultHeight+'px';
testdiv.style.fontSize='30px';
testdiv.style.textAlign='center';
testdiv.innerHTML=iCount;
testdiv.style.top='300px';
testdiv.style.position='absolute';
//也可以在此处预设动画
//testdiv.style.animation='tototop2.0s线性转发';
iCount++;
返回testdiv;
}
document.getElementById('go')。onclick=function(){
var testdiv=createBlock();
testdiv.style.animation='tototop2.0s线性转发';
};
@关键帧totop{
100%{top:-100px;}
}

go
对于转换,您需要两种不同的状态,即更改

仅覆盖两个渲染周期之间的样式。它们仅在(重新)渲染节点时应用。
因此,如果您的setTimeout()在应用“旧”样式之前触发,则stlyes只会被覆盖,并且节点将以目标样式呈现

大多数(桌面)浏览器都追求每秒60帧的帧速率,其间隔为16.7毫秒。所以setTimeout(fn,0)很可能在这之前启动

您可以如您所提到的那样增加超时(我建议至少50毫秒),也可以触发/强制渲染节点;例如,通过询问其大小

要获得节点的大小,浏览器首先必须将所有样式应用于节点,以了解它们如何影响节点。
此外,上下文对css很重要,因此必须将节点添加到DOM的某个位置,以便浏览器能够获得最终计算的样式

长话短说:

document.getElementById('go').onclick = function() {
    var testdiv = createBlock();
    testdiv.style.transition = "top 2.0s linear 0s";

    testdiv.scrollWidth;  //trigger rendering

    //JsBin brags that you don't do anything with the value.
    //and some minifyer may think it is irrelevant and remove it.
    //so, increment it (`++`); the value is readonly, you can do no harm by that.
    //but the mere expression, as shown, already triggers the rendering.

    //now set the target-styles for the transition
    testdiv.style.top = (defaultHeight*-2) + 'px';
};

您需要在类中添加已设置动画的(新的)top值并指定该类,否则转换不知道在哪个top之间设置动画,因为后一个值覆盖了前者。@LGSon新创建的div的初始
top
值为“500px”…为什么需要在CSS类中定义(最佳实践除外)?稍微误读您的问题…将在几秒钟后发布答案。这看起来不错,但使用动画需要定义需要使用CSS设置的关键帧。我正在寻找一个全JS解决方案,在该解决方案中,我不必在文档样式中插入任何新内容。我知道这是非标准的。您知道动画为什么工作吗这里有但没有过渡?@Jonathan.Brink动画在创建时有一个开始值和一个结束值,而过渡没有,因此需要先绘制过渡,然后再为其指定第二个顶值,这将触发过渡。在您的情况下,延迟确实会导致这种情况发生……啊“需要先绘制过渡”可能是理解问题的关键…你说“需要先画”是什么意思?你是说在实际开始过渡之前发生的步骤(通过样式更改)?@Jonathan.Brink-Thomas刚刚发布了一个答案,对其进行了很好的描述。@Jonathan.Brink用一个链接更新了我的答案,以满足您关于如何使用脚本创建<代码>关键帧的要求。在这种情况下,您可以有意利用这种行为,或者只需您在代码中执行操作的顺序。因为就性能而言,您能做的最昂贵的事情是触发不必要的重新渲染;通过更改节点上的某些类名,然后请求受其中一个子节点上的样式影响的任何内容。例如,如位置。因此,在本例中,您要说的是使用
 动画
将通过使用
转换在触发重新渲染时获得性能?不,我是说,你应该记住这种行为,特别是