简体   繁体   English

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

[英]Removing classes from element without affecting css transitions in progress

Ok, I have a situation where I have basically built a little notification dropdown box that happens when the user does something, at the end it transitions to a opacity: 0; 好吧,我有一种情况,我基本上建立了一个小的通知下拉框,当用户做某事时发生,最后它转换为opacity: 0; state. 州。

However, because the user may click something else that will trigger this notification box again I am trying to come up with a way to reset it back to normal without affecting any in-progress transitions and attempting to keep the animation done by CSS rather than JavaScript . 但是,因为用户可能会点击其他会再次触发此通知框的内容,我试图找到一种方法将其重置为正常状态,而不会影响任何正在进行的转换并尝试通过CSS而不是JavaScript来保持动画。

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

HTML: 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>

SCSS: 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;
        }

    }

}

JS: 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
    });

}

I know I can reset it back to normal by doing this in JS: 我知道我可以通过在JS中执行此操作将其重置为正常:

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

...however doing this removes the classes before the transition is finished fading out the opacity and it just vanishes straight away. ...但是这样做会在转换完成之前删除类,淡出不透明度并且它会立即消失。

I know I can do a delay in JS to counteract the CSS delay but doing it that way just doesn't seem a very good way to do it since you have the timings in 2 different places. 我知道我可以在JS中做一个延迟来抵消CSS延迟,但这样做只是看起来不是一个非常好的方法,因为你有两个不同的地方的时间。

Is there any way I can accomplish this whilst keeping the animation done by CSS or will I have to move to using jQuery's animate so I can run the reset procedure once the animation is complete? 有什么方法可以通过CSS保持动画完成,或者我必须转向使用jQuery的animate这样我可以在动画完成后运行重置程序吗?

Ok, I came up with a simple solution after coming up with a convoluted one ha. 好吧,我提出了一个简单的解决方案,提出了一个令人费解的一个哈哈。

Simple solution I should have come up with in the first place was removing any additional added classes before the ajax call; 我应该首先想出的简单解决方案是在ajax调用之前 删除任何其他添加的类; I got too focused on doing it within the ajax block and of course that didn't work, but until I started playing around with the other solution I never tried it. 我太专注于在ajax块中做这件事,当然这不起作用,但在我开始玩其他解决方案之前我从未尝试过。

Any way, the simple solution is simply moving this code: 无论如何,简单的解决方案就是移动这段代码:

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

...above the ajax call, rather than being inside of it. ......在ajax调用之上,而不是在其中。

Then adding this directly under it: 然后直接在它下面添加:

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

With the full function code being: 完整的功能代码是:

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

}

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

The other solution I came up with, whilst not really needed now, I thought I would post it anyway in-case it comes in handy for me (or someone) else in the future. 我提出的另一个解决方案,虽然现在不是真的需要,我想我会发布它,以防它在将来为我(或其他人)派上用场。

It doesn't remove the visible class after the animation is finished (as there is no way that I know of to alert JS when it's done) but the visible class - which I would change the name of if you use this method - doesn't add any new styles, it just runs the animation. 动画结束后它不会删除visible类(因为我没有办法在完成时提醒JS)但是visible类 - 如果你使用这个方法我会更改名称 - 不会添加任何新样式,它只是运行动画。

Here is how I did it: 我是这样做的:

The JavaScript remains the same as the solution above, it's all in the CSS. JavaScript仍然与上面的解决方案相同,它都在CSS中。

TLDR; TLDR;

Basically uses multiple CSS animations to control different states during the effect runtime; 基本上使用多个CSS动画来控制效果运行时期间的不同状态; CodePen at bottom. CodePen在底部。

The changes being in the .visible class and the addition of some @keyframes . 更改在.visible类中,并添加了一些@keyframes

.visible class: 。可见类:

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

As you can see we have gotten rid of any additional styling here - this means when the animation is done, it essentially resets back to normal, which is what we want. 正如你所看到的,我们已经摆脱了任何额外的样式 - 这意味着当动画完成时,它基本上会重置为正常,这就是我们想要的。

Now, let's break down this code: 现在,让我们分解这段代码:

We are running 3 different animations here and it's important to note they don't run one after the other - meaning they don't wait until one is finished until it starts the next one, hence why we needed to include delay settings. 我们在这里运行3种不同的动画,重要的是要注意它们不会一个接一个地运行 - 这意味着它们不会等到一个完成直到它开始下一个动画,因此我们需要包括delay设置。

So first up we start with the slideDown animation: 首先我们从slideDown动画开始:

slideDown 0.8s 0s

If you are new to animations in CSS then basically what this does is sets a delay of 0s before it starts running and the animation runs for 0.8s , and this is the animation: 如果您不0.8s CSS中的动画,那么基本上它的作用是在开始运行之前设置0s 0.8s的延迟并且动画运行0.8s ,这就是动画:

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

So, pretty simple, just slides it down with transform from -100% to 0% and this animation takes 0.8s as we set in our call to this animation. 所以,非常简单,只需transform-100% transform0%即可向下滑动,我们在调用此动画时设置此动画需要0.8s

Now, I wanted this to stay visible for 3 seconds before it started to fade away, but we have a problem; 现在,我希望它在开始消失之前保持可见 3秒 ,但我们遇到了问题; once the animation ends then it goes back to it's standard styling, which in our case means it vanishes as it goes back to transform: translateY(-100%) since we have no extra styles in the .visible class, and we can't put any extra styles in there as then we won't be able to reset it back to it's original state (style wise). 一旦动画结束,它就会回到它的标准样式,在我们的情况下意味着它会在它返回transform: translateY(-100%)时消失transform: translateY(-100%)因为我们在.visible类中没有额外的样式,我们不能在那里放置任何额外的样式,然后我们将无法将其重置回原始状态(风格明智)。

But what do we do? 但我们该怎么办? The fadeAway animation doesn't start for another 3 seconds and at the moment it doesn't have anything to fade away (well it does, but you can't see it as it's hidden). fadeAway动画不会再开始3秒钟,此刻它没有任何消失的东西(确实如此,但你看不到它隐藏了)。

The solution to that was adding another animation - which technically doesn't really animate anything, it just keeps it visible until the fadeAway animation starts. 解决方案是添加另一个动画 - 从技术上讲,它并不能真正动画任何动画,只是在fadeAway动画开始之前一直保持可见。

That's where we get to: 这就是我们到达的地方:

keepThere 3s 0.8s

Now, remembering the settings of our fadeAway animation are: fadeAway 1s 3.8s this means that we have 3 seconds before this animation is going to start and hence before we can control any of the styling with it. 现在,记住我们的fadeAway动画的设置是: fadeAway 1s 3.8s这意味着我们有3秒钟才能开始这个动画,因此我们可以用它来控制任何样式。

So that's where these parameter values comes in - we set the delay to 0.8s so the keepThere animation doesn't start until the slideDown one has finished; 所以这就是这些参数值进来-我们将延迟设置为0.8s ,因此keepThere动画没有启动,直到slideDown一个已经完成; then we set the duration for 3s to counter for the wait time until the fadeAway animation starts, and this is the keepThere animation: 然后我们设置3s的持续时间来计算等待时间,直到fadeAway动画开始,这就是keepThere动画:

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

Since it has the same start and end styling we combine it into one selector of 0%, 100% and as you can see, this does just what it says it does, keeps the element visible for the set duration of 3s until we can control the styling with the fadeAway animation. 由于它具有相同的开始和结束样式,我们将它组合成一个0%, 100%选择器,正如您所看到的,这就像它所说的那样,在3s的设定持续时间内保持元素可见,直到我们可以控制fadeAway动画的样式。

I guess technically you could combine this functionality into the fadeAway animation if you wanted to do the math at what % equals 3 seconds and hence know when to start fading the element away. 我想在技术上你可以将这个功能组合到fadeAway动画中,如果你想在%等于3秒时进行数学计算,那么知道何时开始淡化元素。

Lastly we have the fadeAway animation: 最后我们有fadeAway动画:

fadeAway 1s 3.8s

Now as we have discussed above, we already know why we have set the delay to 3.8s , the 0.8s offset to allow the slideDown animation to run and an additional 3s delay as that's how long we want the element to be visible for until it starts fading away and then of course the fade takes 1s to complete. 现在我们已经讨论过了,我们已经知道为什么我们将delay设置为3.8s0.8s偏移以允许slideDown动画运行以及额外的3s延迟,因为这是我们希望元素可见的时间,直到它开始消失然后当然淡出需要1s才能完成。

The animation for this is: 这个动画是:

@keyframes fadeAway {
    0%, 100% {
        transform: translateY(0%);
    }
    0% {
        opacity: 1;
    }
    100% {
        opacity: 0;
    }
}

Now, since the keepThere animation has completed, we have to make sure to keep the element visible so the fade has something visible to actually fade away, that's why we make sure to include the style transform: translateY(0%); 现在,由于keepThere动画已经完成,我们必须确保元素可见,因此淡入淡出有一些可见的东西实际消失,这就是为什么我们确保包含样式transform: translateY(0%); as a value from start to finish; 作为从头到尾的价值; after that it's quite obvious what it's doing I think. 之后,我认为它的作用非常明显。

Put it all together and you get: 把它们放在一起,你得到:

.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;
    }
}

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

Then of course to be able to run it again the class has to be re-added and hence that was the purpose of removing the .visible class at the start of each run (before the ajax call) and then when it gets re-added during the ajax call it runs again. 然后当然为了能够再次运行它,必须重新添加类,因此这是在每次运行开始时(在ajax调用之前)删除.visible类然后重新添加时的目的。在ajax调用期间它再次运行

Thanks to @Nathaniel Flick for sharing the link that led me down this path to begin with :) 感谢@Nathaniel Flick分享链接,让我沿着这条道路开始:)

Well, hopefully that comes in handy for someone seeing as I am no longer going to use that option ha! 嗯,希望这对于看到我不再使用该选项的人来说很方便哈哈!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM