淡入新元素的可靠方法
Reliable way to fade in new element
在我的应用程序中,我每秒创建一个新元素。它们应该在创建时淡入。这是我的做法:
window.setInterval(() => {
const element = document.createElement('div');
element.classList.add('dot', 'hidden');
document.getElementById('content').appendChild(element);
element.classList.remove('hidden');
}, 1000);
.dot {
display: inline-block;
width: 10px;
height: 10px;
border-radius: 50%;
background-color: rgba(255, 255, 255, .7);
margin: 0 5px 5px 0;
transition: opacity 1s;
}
.hidden {
opacity: 0;
}
我原以为这会使转换工作正常,但事实并非如此。我还尝试在延迟后删除 hidden
class,如下所示:
setTimeout(() => element.classList.remove('hidden'), 100);
这很有趣,因为它只有在延迟足够长的情况下才有效。如果我将它设置为 10 毫秒,一些点会淡入,而另一些会立即出现。
有没有更好、更简单、更可靠的方法让它工作,不用猜测 setTimeout()
的延迟?
您可以使用 CSS animations 并避免使用 JavaScript 如果它是您想要的简单 fade-in。这只会 运行 当 DOM 节点被绘制到屏幕上时。如果您需要对动画进行更高级的控制,那么您可以使用 JS。
@keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.dot {
display: inline-block;
width: 10px;
height: 10px;
border-radius: 50%;
background-color: rgba(255, 255, 255, .7);
margin: 0 5px 5px 0;
animation: 1s linear fadein;
}
您原来的问题是有道理的,因为您在 setTimeout
块的同一函数内添加隐藏的 class 并将其删除。请记住,浏览器只有在您的函数完成执行后才有机会重新呈现。这意味着在您添加 hidden
class 的行中根本没有用,因为它稍后会在函数中立即删除(在浏览器可以进行渲染之前)。
我建议插入您的 DOM 元素并使用 setTimeout
或 requestAnimationFrame
重置它。也因为 setInterval
和 setTimeout
的时间不完全可靠,使用一个元素的 transitionend
事件来触发下一个元素的添加可能是有意义的。
(function() {
const container = document.getElementById('container');
let count = 0;
function addElement() {
const div = document.createElement('div');
div.innerHTML = 'item ' + ++count
container.append(div);
div.classList.add('item')
div.addEventListener('transitionend', addElement)
setTimeout(function() {
div.classList.add('show')
}, 0)
}
addElement()
})()
div {}
div.item {
opacity: 0;
transition: opacity 1s;
}
div.item.show {
opacity: 1;
}
<hr>
<div id="container">
</div>
Css transition
隐藏东西时效果最好。
所以这是一个仅使用 javascript 的解决方案。
window.setInterval(() => {
const element = document.createElement('div');
element.classList.add('dot');
document.getElementById('content').appendChild(element);
fade(element,0.1);
}, 1000);
// This will inc opacity by 0.1 each 100ms
function fade(item, i){
i += 0.1;
item.style.opacity = i;
if (i< 1)
setTimeout(()=> fade(item,i), 100);
}
.dot {
display: inline-block;
width: 10px;
height: 10px;
border-radius: 50%;
background-color: rgba(255, 255, 255, .7);
margin: 0 5px 0px 5px;
}
#content {
background:black;
}
<div id="content"></div>
在我的应用程序中,我每秒创建一个新元素。它们应该在创建时淡入。这是我的做法:
window.setInterval(() => {
const element = document.createElement('div');
element.classList.add('dot', 'hidden');
document.getElementById('content').appendChild(element);
element.classList.remove('hidden');
}, 1000);
.dot {
display: inline-block;
width: 10px;
height: 10px;
border-radius: 50%;
background-color: rgba(255, 255, 255, .7);
margin: 0 5px 5px 0;
transition: opacity 1s;
}
.hidden {
opacity: 0;
}
我原以为这会使转换工作正常,但事实并非如此。我还尝试在延迟后删除 hidden
class,如下所示:
setTimeout(() => element.classList.remove('hidden'), 100);
这很有趣,因为它只有在延迟足够长的情况下才有效。如果我将它设置为 10 毫秒,一些点会淡入,而另一些会立即出现。
有没有更好、更简单、更可靠的方法让它工作,不用猜测 setTimeout()
的延迟?
您可以使用 CSS animations 并避免使用 JavaScript 如果它是您想要的简单 fade-in。这只会 运行 当 DOM 节点被绘制到屏幕上时。如果您需要对动画进行更高级的控制,那么您可以使用 JS。
@keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.dot {
display: inline-block;
width: 10px;
height: 10px;
border-radius: 50%;
background-color: rgba(255, 255, 255, .7);
margin: 0 5px 5px 0;
animation: 1s linear fadein;
}
您原来的问题是有道理的,因为您在 setTimeout
块的同一函数内添加隐藏的 class 并将其删除。请记住,浏览器只有在您的函数完成执行后才有机会重新呈现。这意味着在您添加 hidden
class 的行中根本没有用,因为它稍后会在函数中立即删除(在浏览器可以进行渲染之前)。
我建议插入您的 DOM 元素并使用 setTimeout
或 requestAnimationFrame
重置它。也因为 setInterval
和 setTimeout
的时间不完全可靠,使用一个元素的 transitionend
事件来触发下一个元素的添加可能是有意义的。
(function() {
const container = document.getElementById('container');
let count = 0;
function addElement() {
const div = document.createElement('div');
div.innerHTML = 'item ' + ++count
container.append(div);
div.classList.add('item')
div.addEventListener('transitionend', addElement)
setTimeout(function() {
div.classList.add('show')
}, 0)
}
addElement()
})()
div {}
div.item {
opacity: 0;
transition: opacity 1s;
}
div.item.show {
opacity: 1;
}
<hr>
<div id="container">
</div>
Css transition
隐藏东西时效果最好。
所以这是一个仅使用 javascript 的解决方案。
window.setInterval(() => {
const element = document.createElement('div');
element.classList.add('dot');
document.getElementById('content').appendChild(element);
fade(element,0.1);
}, 1000);
// This will inc opacity by 0.1 each 100ms
function fade(item, i){
i += 0.1;
item.style.opacity = i;
if (i< 1)
setTimeout(()=> fade(item,i), 100);
}
.dot {
display: inline-block;
width: 10px;
height: 10px;
border-radius: 50%;
background-color: rgba(255, 255, 255, .7);
margin: 0 5px 0px 5px;
}
#content {
background:black;
}
<div id="content"></div>