元素创建后立即触发转换
Immediately trigger transition after element created
我正在尝试创建一个动作,其中创建 div 并立即向上 "floats" 直到它离开屏幕。
为了实现这一点,我尝试使用 CSS transition,它将完全由 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
};
当快速点击 "go" 按钮 (see JSBin) 时,div 只会偶尔出现(可能是由于上述时间问题)。
如果您增加 setTimeout
的延迟值,您会发现过渡几乎总是有效。
有没有办法在创建元素后立即确定性地启动转换(而不必诉诸延迟)?
另一种方法是使用 animation
如果您想使用 javascript 动态创建 keyframes
,这里有一个很好的 post 显示:
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 = '300px';
testdiv.style.position = 'absolute';
// you can preset the animation here as well
//testdiv.style.animation = 'totop 2.0s linear forwards';
iCount++;
return testdiv;
}
document.getElementById('go').onclick = function() {
var testdiv = createBlock();
testdiv.style.animation = 'totop 2.0s linear forwards';
};
@keyframes totop {
100% { top: -100px; }
}
<button id="go">go</button>
对于转换,您需要两个不同的状态。一个变化。
两个渲染周期之间的样式只会被覆盖。它们仅在(重新)渲染节点时应用。
因此,如果您的 setTimeout() 在应用 "old" 样式之前触发,stlyes 只会被覆盖,并且您的节点将使用目标样式呈现。
阿法克。大多数(桌面)浏览器都争取 60fps 的帧速率,这使得间隔为 16.7ms。所以 setTimeout(fn,0) 很可能会在那之前触发。
您可以像您提到的那样增加超时(我建议至少 50 毫秒),或者您可以 trigger/enforce 渲染节点;例如通过询问它的大小。
要获得节点的大小,浏览器首先必须将所有样式应用到节点,以了解它们如何影响它。
此外,上下文对 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';
};
我正在尝试创建一个动作,其中创建 div 并立即向上 "floats" 直到它离开屏幕。
为了实现这一点,我尝试使用 CSS transition,它将完全由 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
};
当快速点击 "go" 按钮 (see JSBin) 时,div 只会偶尔出现(可能是由于上述时间问题)。
如果您增加 setTimeout
的延迟值,您会发现过渡几乎总是有效。
有没有办法在创建元素后立即确定性地启动转换(而不必诉诸延迟)?
另一种方法是使用 animation
如果您想使用 javascript 动态创建 keyframes
,这里有一个很好的 post 显示:
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 = '300px';
testdiv.style.position = 'absolute';
// you can preset the animation here as well
//testdiv.style.animation = 'totop 2.0s linear forwards';
iCount++;
return testdiv;
}
document.getElementById('go').onclick = function() {
var testdiv = createBlock();
testdiv.style.animation = 'totop 2.0s linear forwards';
};
@keyframes totop {
100% { top: -100px; }
}
<button id="go">go</button>
对于转换,您需要两个不同的状态。一个变化。
两个渲染周期之间的样式只会被覆盖。它们仅在(重新)渲染节点时应用。
因此,如果您的 setTimeout() 在应用 "old" 样式之前触发,stlyes 只会被覆盖,并且您的节点将使用目标样式呈现。
阿法克。大多数(桌面)浏览器都争取 60fps 的帧速率,这使得间隔为 16.7ms。所以 setTimeout(fn,0) 很可能会在那之前触发。
您可以像您提到的那样增加超时(我建议至少 50 毫秒),或者您可以 trigger/enforce 渲染节点;例如通过询问它的大小。
要获得节点的大小,浏览器首先必须将所有样式应用到节点,以了解它们如何影响它。
此外,上下文对 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';
};