从元素中删除类而不影响正在进行的css转换

Bre*_*ett 7 javascript css jquery transition css-transitions

好吧,我有一种情况,我基本上建立了一个小的通知下拉框,当用户做某事时发生,最后它转换到一个opacity: 0;状态.

但是,因为用户可能会点击其他会再次触发此通知框的内容,我试图找到一种方法将其重置为正常状态,而不会影响任何正在进行的转换并尝试通过CSS而不是JavaScript来保持动画.

CodePen:http ://codepen.io/gutterboy/pen/WoEydg

HTML:

<a href="#">Open Notify Window</a>

<div id="top_notify" class="top-notify">
    <div class="container-fluid">
        <div class="row">
            <div class="content col-xs-12">
                <div class="alert" role="alert"></div>
            </div>
        </div>
    </div>
</div>
Run Code Online (Sandbox Code Playgroud)

SCSS:

body {
    text-align: center;
    padding-top: 150px;
}

.top-notify {
    position: fixed;
    top: 0;
    width: 100%;
    z-index: 9999;

    .content {
        text-align: center;
        background-color: transparent;
        transform-style: preserve-3d;
    }

    .alert {
        display: inline-block;
        transform: translateY(-100%);
        min-width: 250px;
        max-width: 500px;
        border-top-left-radius: 0;
        border-top-right-radius: 0;

        &.visible {
            transform: translateY(0%);
            transition: 0.8s 0s, opacity 1s 3.8s;
            opacity: 0;
        }

    }

}
Run Code Online (Sandbox Code Playgroud)

JS:

$('a').on('click', function(e){
    e.preventDefault();
    myFunc();
});

function myFunc() {

    // Set file to prepare our data
    var loadUrl = "https://crossorigin.me/http://codepen.io/gutterboy/pen/ObjExz.html";

    // Run request

    getAjaxData(loadUrl, null, 'POST', 'html')

            .done(function(response) {

                var alert_el = $('#top_notify').find('.alert');

                // Update msg in alert box
                alert_el.text(response);
                alert_el.addClass('alert-success');

                // Slide in alert box
                alert_el.addClass('visible');

            })

            .fail(function() {
                alert('Problem!!');
            });

    // End

}

function getAjaxData(loadUrl, dataObject, action, type) {

    return jQuery.ajax({
        type: action,
        url: loadUrl,
        data: dataObject,
        dataType: type
    });

}
Run Code Online (Sandbox Code Playgroud)

我知道我可以通过在JS中执行此操作将其重置为正常:

$('#top_notify').find('.alert').removeClass().addClass('alert'); // The classes it ends up with vary
Run Code Online (Sandbox Code Playgroud)

...但是这样做会在转换完成之前删除类,淡出不透明度并且它会立即消失.

我知道我可以在JS中做一个延迟来抵消CSS延迟,但这样做只是看起来不是一个非常好的方法,因为你有两个不同的地方的时间.

有没有什么方法可以实现这一点,同时保持动画由CSS完成,或者我将不得不转向使用jQuery,animate所以我可以在动画完成后运行重置程序?

Bre*_*ett 1

好吧,我在想出了一个复杂的一哈之后想出了一个简单的解决方案。

我首先应该想到的简单解决方案是在调用之前删除任何额外添加的类;我太专注于在区块内完成这件事,当然这不起作用,但在我开始尝试其他解决方案之前,我从未尝试过。ajaxajax

无论如何,简单的解决方案就是移动这段代码:

 var alert_el = $('#top_notify').find('.alert');
Run Code Online (Sandbox Code Playgroud)

...在ajax通话之上,而不是在通话内部。

然后直接在其下面添加:

alert_el.removeClass('visible alert-success alert-info alert-danger alert-warning');
Run Code Online (Sandbox Code Playgroud)

完整的功能代码是:

function myFunc() {

    // Set file to prepare our data
    var loadUrl = "https://crossorigin.me/http://codepen.io/gutterboy/pen/ObjExz.html";

    var alert_el = $('#top_notify').find('.alert');

    alert_el.removeClass('visible alert-success alert-info alert-danger alert-warning');

    // Run request

    getAjaxData(loadUrl, null, 'POST', 'html')

            .done(function(response) {

                // Update msg in alert box
                alert_el.text(response);
                alert_el.addClass('alert-success');

                // Slide in alert box
                alert_el.addClass('visible');

            })

            .fail(function() {
                alert('Problem!!');
            });

    // End

}
Run Code Online (Sandbox Code Playgroud)

代码笔: http: //codepen.io/gutterboy/pen/xRXbXy

我提出的另一个解决方案,虽然现在并不真正需要,但我想我无论如何都会发布它,以防它将来对我(或其他人)有用。

不会在动画完成后删除该类visible(因为据我所知,在动画完成时没有办法提醒 JS),但是该类visible如果您使用此方法,我将更改其名称)不会添加任何新样式,它都只是运行动画。

我是这样做的:

JavaScript 与上面的解决方案相同,全部在 CSS 中。

太长了;

基本上使用多个CSS动画来控制效果运行时的不同状态;代码笔在底部。

更改发生在.visible类中并添加了一些@keyframes.

.可见类:

&.visible {
    animation: slideDown 0.8s 0s, keepThere 3s 0.8s, fadeAway 1s 3.8s;
}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,我们在这里去掉了任何额外的样式——这意味着当动画完成时,它基本上会重置回正常状态,这就是我们想要的。

现在,让我们分解一下这段代码:

我们在这里运行 3 个不同的动画,重要的是要注意它们不会一个接一个地运行 - 这意味着它们不会等到一个动画完成后才开始下一个动画,因此我们需要包含设置delay

首先我们从动画开始slideDown

slideDown 0.8s 0s

如果您不熟悉 CSS 中的动画,那么基本上它的作用是0s在开始运行之前设置一个延迟,并且动画运行0.8s,这就是动画:

@keyframes slideDown {
    0% {
        transform: translateY(-100%);
    }
    100% {
        transform: translateY(0%);
    }
}
Run Code Online (Sandbox Code Playgroud)

transform所以,非常简单,只需使用from -100%to向下滑动0%,该动画就会0.8s按照我们在调用该动画时设置的方式呈现。

现在,我希望它在开始消失之前保持可见3秒,但我们有一个问题;一旦动画结束,它就会回到它的标准样式,在我们的例子中,这意味着它会消失,因为transform: translateY(-100%)我们在类中没有额外的样式.visible,并且我们不能在其中放置任何额外的样式,因为那时我们赢了无法将其重置回原始状态(风格方面)。

但我们该怎么办呢?动画fadeAway在 3 秒后才开始,此时它没有任何东西可以消失(确实如此,但你看不到它,因为它被隐藏了)。

解决方案是添加另一个动画 - 从技术上讲,它并没有真正为任何东西设置动画,它只是让它保持可见,直到fadeAway动画开始。

这就是我们要做的:

keepThere 3s 0.8s

fadeAway现在,记住我们的动画设置是:fadeAway 1s 3.8s这意味着在该动画开始之前我们有3 秒的时间,因此我们可以用它来控制任何样式。

这就是这些参数值的用武之地——我们将延迟设置为,0.8s以便动画在动画完成keepThere之前不会开始;slideDown然后我们设置持续时间来3s计数器动画开始之前的等待时间fadeAway,这就是keepThere动画:

@keyframes keepThere {
    0%, 100% {
        transform: translateY(0%);
    }
}
Run Code Online (Sandbox Code Playgroud)

由于它具有相同的开始和结束样式,我们将其组合到一个选择器中0%, 100%,正如您所看到的,这正如它所说的那样,在设定的持续时间内保持元素可见,3s直到我们可以使用动画控制样式fadeAway

我想从技术上讲,fadeAway如果您想以 % 等于3 秒进行数学计算,从而知道何时开始淡出元素,您可以将此功能合并到动画中。

最后我们有fadeAway动画:

fadeAway 1s 3.8s

现在,正如我们上面所讨论的,我们已经知道为什么要设置 to delay3.8s允许0.8s动画slideDown运行的偏移量和额外的3s延迟,因为这就是我们希望元素可见的时间,直到它开始消失,然后当然淡入淡出需要1s完成。

这个动画是:

@keyframes fadeAway {
    0%, 100% {
        transform: translateY(0%);
    }
    0% {
        opacity: 1;
    }
    100% {
        opacity: 0;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,由于keepThere动画已经完成,我们必须确保元素保持可见,以便淡入淡出时有一些可见的东西真正消失,这就是为什么我们确保transform: translateY(0%);从开始到结束将样式作为值包含在内;之后我认为它在做什么就很明显了。

把它们放在一起,你会得到:

.top-notify {
    position: fixed;
    top: 0;
    width: 100%;
    z-index: 9999;

    .content {
        text-align: center;
        background-color: transparent;
        transform-style: preserve-3d;
    }

    .alert {
        display: inline-block;
        transform: translateY(-100%);
        min-width: 250px;
        max-width: 500px;
        border-top-left-radius: 0;
        border-top-right-radius: 0;

        &.visible {
            animation: slideDown 0.8s 0s, keepThere 3s 0.8s, fadeAway 1s 3.8s;
        }

    }

}

@keyframes slideDown {
    0% {
        transform: translateY(-100%);
    }
    100% {
        transform: translateY(0%);
    }
}

@keyframes keepThere {
    0%, 100% {
        transform: translateY(0%);
    }
}

@keyframes fadeAway {
    0%, 100% {
        transform: translateY(0%);
    }
    0% {
        opacity: 1;
    }
    100% {
        opacity: 0;
    }
}
Run Code Online (Sandbox Code Playgroud)

代码笔: http: //codepen.io/gutterboy/pen/QGqwBg

当然,为了能够再次运行它,必须重新添加类,因此这就是.visible在每次运行开始时(在 ajax 调用之前)删除该类的目的,然后在运行期间重新添加该类。 ajax调用它再次运行

感谢@Nathaniel Flick 分享了引导我走上这条路的链接:)

好吧,希望这对某人有用,因为我不再使用该选项了哈!