【问题标题】:Css transition and setTimeoutCss 过渡和 setTimeout
【发布时间】:2019-10-17 11:20:17
【问题描述】:

我有一个消息元素,我在函数中添加到我的页面:

 const markup = `<div class="todolist__message todolist__message${status? "--ok":"--err"}">${msg}</div>`;

    elements.tdl.insertAdjacentHTML('beforeend', markup);

    if(fade) {
        const message = document.querySelector('.todolist__message');

        // Change the message opacity
        message.style.opacity = '0';

        // Remove the message element
        setTimeout(() => {
            document.querySelector('.todolist__message').parentElement.removeChild(message);
        }, 2000);
    }

然后我添加 css 属性:

    opacity: 1;
    transition: opacity 1s;

我不明白为什么,当我将消息不透明度更改为 0 时,过渡似乎不起作用并且元素立即消失?

我必须重写代码,将样式更改放在 setTimeout 中,并添加一个额外的 setTimeout 用于元素移除:

const markup = `
    <div class="todolist__message todolist__message${status? "--ok":"--err"}">${msg}</div>
`;

elements.tdl.insertAdjacentHTML('beforeend', markup);

if(fade) {

    setTimeout(() => {
        const message = document.querySelector('.todolist__message');

        // Change the message opacity
        message.style.opacity = '0';

        // Remove the message
        setTimeout(() => document.querySelector('.todolist__message').parentElement.removeChild(message), 2000);
    }, 2000);
}

有人介意解释为什么第一个代码块会导致消息立即消失,而不是应用 css 转换吗?

谢谢

** 请参阅下面的答案,了解动画完成后删除元素的方法。

【问题讨论】:

  • 尝试添加类而不是更新样式。
  • 是的,干杯,这可能比 2x 超时要好,但仍然对为什么上面没有按我预期的那样工作感兴趣?
  • 您的代码正在运行,请参阅我的回答。 PS:你把这个transition规则放在哪里了,你能用选择器显示你的css吗?

标签: javascript css css-animations


【解决方案1】:

这行得通:

var msg = "hello World";

const markup = `
    <div class="todolist__message todolist__message">${msg}</div>
`;

wrapper.innerHTML = markup;
btn.addEventListener('click', function() {

        const message = document.querySelector('.todolist__message');

        // Change the message opacity
        message.style.opacity = '0';

        // Remove the message
        setTimeout(() => document.querySelector('.todolist__message').parentElement.removeChild(message), 2000);
});
.todolist__message {
  transition: opacity 1s;
}
<div id="wrapper"></div>
<button id="btn">delete</button>

【讨论】:

  • 是的,这是第一个不起作用的代码示例,没有两个 setTimeouts :)
  • @NickW 我认为问题在于您正在添加并立即删除,当您需要运行 setTimeout(0) 时,JS 中有一些与 CSS 相关的东西,因此代码在下一个事件循环中运行因为css更新发生在JS事件循环中。
  • 嗯,我的意思是很高兴知道我没有错过任何太明显的东西,而且你可能是对的 - 但我很难看到你的代码真的有什么不同,会有试试看,谢谢
  • @NickW 在我的代码中删除是在单击事件中,因此它与您的代码中的时间不同。如果您将 setTimeout(0) 添加到您的代码中,它应该可以工作,因为事件循环。观看此视频Jake Archibald: In The Loop - JSConf.Asia
【解决方案2】:

问题是你试图同时应用opacity: 0,你应用了转换。 给transition工作;您需要先添加过渡类,然后在 setTimeout 中添加opacity

【讨论】:

  • 你的意思是因为我几乎在应用不透明度的同时创建了类本身?在不透明度设置为零之前,技术上已经应用了过渡,因为它在元素的 css 中(以及不透明度:1)
  • 那是一回事。创建一个新元素或添加具有transition 属性的“类”。
【解决方案3】:

对于任何感兴趣的人,第二个超时和元素的删除应该替换为元素上的 transitionend 事件监听器,该监听器调用一个在动画完成后删除元素的方法,而不是将 setTimeouts 与动画同步延迟+持续时间:

window.addEventListener(this.whichTransitionEvent(), function(e) {
    if(e.target.classList.contains('todolist__message')) {
        toDoListView.deleteMessage(e.target);
    }
}); 

删除功能:

export const deleteMessage = element => {
    if(element) {
        element.parentElement.removeChild(element);
    }
};

还有 David Walsh 的前缀检查函数:

whichTransitionEvent() {
    let t;
    const el = document.createElement('fake-element');
    const transitions = {
        'transition': 'transitionend',
        'OTransition': 'oTransitionEnd',
        'MozTransition': 'transitionend',
        'WebkitTransition': 'webkitTransitionEnd'
    }

    for(t in transitions) {
        if(el.style[t] !== undefined)
            return transitions[t];
    }
}

我认为我做对了 - 它似乎可以正常工作!

【讨论】:

    猜你喜欢
    • 2014-04-21
    • 2014-04-24
    • 1970-01-01
    • 2015-06-22
    • 2018-09-09
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    相关资源
    最近更新 更多