Detect the end of specific CSS animation of an element - javascript

We have two CSS animation keyframes that will be added or removed to the element using Javascript:
One for hiding the element by animating it from top to bottom:
upperGuideText.classList.add("upperGuideAnimeHide"); // Hide CSS KeyFrames
And another for showning the element by animating it from bottom to top:
upperGuideText.classList.add("upperGuideAnimeShow"); // Show CSS KeyFrames
Simply we add and remove them via classes to the element.
Then we create a function to handle these show and hide animations named guideReveal.
Each time we invoke guideReveal and pass a text to the function there will be two steps:
First, we hide the last text (animate it from top to bottom)
Then we add and animate the new text that is just passed to the function (animate it from bottom to top).
The code is simple, please have a look at it:
function guideReveal(text){
// Hide the `upperGuideText` on each guideReveal function execution
upperGuideText.classList.add("upperGuideAnimeHide"); // Hide CSS KeyFrames
upperGuideText.classList.remove("upperGuideAnimeShow"); // Show CSS KeyFrames
// After a delay show another `upperGuideText`
setTimeout(function(){
upperGuideText.innerHTML = `${text}`;
upperGuideText.classList.add("upperGuideAnimeShow"); // Show CSS KeyFrames
upperGuideText.classList.remove("upperGuideAnimeHide"); // Hide CSS KeyFrames
//Track end of only `upperGuideAnimeShow` animation! It's not working right now
upperGuideText.addEventListener("webkitAnimationEnd", function(){
console.log('Animation of guide ended..!')
});
}, 1000);
}
So far when the text shows up and when the text hides down we can track the end of the animation using webkitAnimationEnd but, I don't want to track the end of hide animation...
How can we Track the end of only upperGuideAnimeShow animation!

You could look for a specific animationName property of the animationend event, e.g.
let d = document.querySelector('div')
d.addEventListener('animationend', function(ev) {
if (ev.animationName === 'fade') {
alert('end')
}
})
div {
margin: 100px;
width: 100px;
height: 100px;
background: yellowgreen;
animation: fade 5s linear 0s 1,
resize 2s linear 0s forwards;
}
#keyframes fade {
from { opacity: 1 }
to { opacity: 0 }
}
#keyframes resize {
from { transform: scaleX(1) }
to { transform: scaleX(2) }
}
<div></div>
in this example I've set two dfferent animations, but in the event handler I checked for the fade animation.

Related

is it possible to have a css animation play whilst left click is being held?

I want a CSS animation to play when left click is being held (anywhere on the page), then when you let go, it plays a different animation, whilst it is being held it should stay on the last keyframe of the first animation, until you let go. like a normal default CSS animation just instead of playing out constantly, its only when the mouse is held, and then another for when you let go.
this can be done in either JS or CSS, I dont mind, whatever works, works.
my current code:
body{
background-color: #1c1c1c;
}
.animate{
background-color: white;
position: relative;
height: 50px;
width: 59px;
animation-name: mousein;
animation-duration: 0.4s;
animation-fill-mode: forwards;
}
/*To play when you hold on left click*/
#keyframes mousein{
0%{rotate: 0deg;}
100%{rotate:45deg;} /*to hold when the animation has finished but you dont release*/
}
/* to be played when the mouse is let go of */
#keyframes mouseout{
0%{rotate: 45deg;}
100%{rotate:0deg;}
}
<body>
<div class="animate">
</div>
</body>
I'm not 100% sure what your end idea is but I think you are looking for something like the following which really is just a toggle between mousedown and mouseup events with respect to the small amount of animation-duration you have.
You can use css variables passed from javascript to css through the root element. Set the keyframe animations property values using these css variables. You can set the opposing start and finish keyframes to the same degree initially. Then basically toggle their states of degrees as you listen for the two events in concert with each other.
If this is not what you were after let me know and I will edit the code or remove this answer.
// i did not include the use of a variable to track states as setProperty
// and the very eventListener does that for this example... this can easily be reimplemented
var mouseIsDown = false;
// pass in the varaible name and value, since they
// are the finish of in and start of out, their
// values can be the same value at the same time so only
// one variable is needed to manipulate both keyframe animations
// set the css variable value initially
document.documentElement.style.setProperty('--mousein', '0deg')
// the event listener for mousedown
window.addEventListener('mousedown', function() {
// set the mousein variable to 45deg
document.documentElement.style.setProperty('--mousein', '45deg')
});
window.addEventListener('mouseup', function() {
// set the mousein variable to 0deg
document.documentElement.style.setProperty('--mousein', '0deg')
});
body {
background-color: #1c1c1c;
}
.animate {
background-color: white;
position: relative;
height: 50px;
width: 59px;
animation-name: mousein;
animation-duration: 0.4s;
animation-fill-mode: forwards;
}
/*To play when you hold on left click*/
#keyframes mousein {
0% {
rotate: 0deg;
}
100% {
rotate: var(--mousein);
}
/*to hold when the animation has finished but you dont release*/
}
/* to be played when the mouse is let go of */
#keyframes mouseout {
0% {
rotate: var(--mousein);
}
100% {
rotate: 0deg;
}
}
<body>
<div class="animate">
</div>
</body>

Cant control the Numerical variable trigger condition with the OnClickEvent. OnClickEvent triggering multiple times

first time post here. a beginner.
What I'm trying to do here is that:
I'm trying to display an image of a silhouette of a person. And with every click, the current image fades out and another image of the same person (different position/location) fades in. kind of like an animation except very bare bones.
I made a variable that supposedly controls when certain images fade in or out(var currentscene).The button that calls the function covers the entire page and is invisible because I want the animation to move frame by frame with a click anywhere from the page.
('stand' is an image of a boy standing and 'sit' is an image of a boy sitting) edit: in the example it becomes squareblue and squarered.
(fade-in and fade-out are classes that I add to the image so the transition triggers)
And yet the problem is that a single click will fade in both pictures, as if the number on the variable (currentscene) doesn't matter or the onclick event registered infinite number of clicks or something like that.
Im trying to make the blue square fade in on the first click and the blue fade out and the red fade in on the second click of the button.
If there is a fix to this that would be helpful. If there is a whole another way to do what I'm trying to accomplish, I'm all ears. Although I've tried looking into arrays and EventListeners but I haven't been successful.
heres a recreation of the problem:
var currentscene = 0;
function next() {
currentscene++;
if (currentscene = 1) {
var element = document.getElementById("blue");
element.classList.add("fade-in");
}
if (currentscene = 2) {
var element = document.getElementById("blue");
element.classList.add("fade-out");
var element = document.getElementById("red");
element.classList.add("fade-in");
}
}
.squareblue {
height: 50px;
width: 50px;
top: 50px;
background-color: blue;
position: absolute;
opacity: 0;
animation-fill-mode: forwards;
}
.squarered {
height: 50px;
width: 50px;
top: 100px;
background-color: red;
position: absolute;
opacity: 0;
animation-fill-mode: forwards;
}
.fade-out {
animation: fadeOut ease 2s
}
#keyframes fadeOut {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
.fade-in {
animation: fadeIn ease 2s
}
#keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
<div2 id="blue" class="squareblue"></div2>
<div2 id="red" class="squarered"></div2>
<button class="button" onclick="next()">next</button>

jquery toggleClass with fade in effect

I'm using jQuery to toggle between my light theme and dark theme:
$(".theme__switch").on("click", () => {
$("body").toggleClass("light__theme dark__theme");
});
My goal is to attach a fade-in animation to both these classes.
It works for light__theme on load, and when I toggle back from dark__theme, but when I try to add the fade-in animation to my dark__theme, the animation doesn't work for either themes
I start with: <body class="light__theme">
.light__theme {
animation: fadein 2s;
}
#keyframes fadein {
from {
opacity:0;
}
to {
opacity:1;
}
}
which works fine, but when I try to attach the animation to my
dark__theme class like so:
.dark__theme {
--background: #121212;
--text: #f2f3f4;
background: var(--background);
// adding the animation in
animation: fadein 2s;
}
I don't get the fade-in animation, and it also removes the animation from my light theme.
The classes are being toggled correctly, I can see that when inspecting the <body> in dev tools, but I'm not sure whats causing my issue. Perhaps the way I'm calling the animation in my css?
I'd really appreciate any help on this one.. thanks for looking!
You need to add reverse to the animation for dark__theme:
.dark__theme {
--background: #121212;
--text: #f2f3f4;
background: var(--background);
// adding the animation in
animation: fadein 2s reverse;
}
Animation MDN

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; 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.
CodePen:http://codepen.io/gutterboy/pen/WoEydg
HTML:
Open Notify Window
<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:
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:
$('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:
$('#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.
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?
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; 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.
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.
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
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.
Here is how I did it:
The JavaScript remains the same as the solution above, it's all in the CSS.
TLDR;
Basically uses multiple CSS animations to control different states during the effect runtime; CodePen at bottom.
The changes being in the .visible class and the addition of some #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.
So first up we start with the slideDown animation:
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:
#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.
Now, I wanted this to stay visible for 3 seconds before it started to fade away, but we have a problem; 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).
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).
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.
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.
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; then we set the duration for 3s to counter for the wait time until the fadeAway animation starts, and this is the keepThere animation:
#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.
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.
Lastly we have the fadeAway animation:
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.
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%); 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
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.
Thanks to #Nathaniel Flick for sharing the link that led me down this path to begin with :)
Well, hopefully that comes in handy for someone seeing as I am no longer going to use that option ha!

making navigation items separate fading images

I'm building a simple navigation menu with four links. The menu has a greyscaled background image sliced into four parts that when hovered over will fade in a colored section of the background image, basically creating a saturation/desaturation effect on mouse over. The code im using works but only for one of the four slices. I need to figure out how to get each item to fade in separately. While messing with the code, ive been able to get either, one or all to fade in on hover, but can't figure out how to "break" them up.
$(document).ready(function () {
$('div.menu').hover(function() {
var fade = $('.one', this);
if (fade.is(':animated')) {
fade.stop().fadeTo(250, 1);
} else {
fade.fadeIn(250);
}
}, function () {
var fade = $('.one', this);
if (fade.is(':animated')) {
fade.stop().fadeTo(500, 0);
} else {
fade.fadeOut(500);
}
});
});
below are pics of whats happening
http://i.imgur.com/KZBlHxo.jpg
http://i.imgur.com/20iW8UM.jpg
Couldnt you do this using CSS? Here is a sample with transitions
.menu-item{
opacity:1;
transition: opacity .2s linear;
}
.menu-item:hover {
opacity:0;
}
Here is another with CSS animation
.menu-item:hover{
animation: fade;
-webkit-animation: fade;
}
#keyframes fade{
from{opacity:1;}
to {opacity:0;}
}
#-webkit-keyframes fade{
from{opacity:1;}
to {opacity:0;}
}
You can add delay parameters, timing, iteration count, etc.
http://www.w3schools.com/css/css3_animations.asp

Categories

Resources