I want to stay with final properties of css animation, but remove animation property itself, exmeple:
#keyframes('foo')
{
0% { opacity: 0; }
to { opacity: 1; }
}
at the begining :
.my_element
{
opacity: 0;
}
I apply animation by Javascript, so I got :
.my_element
{
opacity: 0;
}
element.style
{
animation: foo 1s forwards; #with opacity: 1; at the end.
}
And now I need clean up :
.my_element
{
opacity: 0;
}
element.style
{
opacity: 1;
}
How can I do that?
This does exactly what you're asking. On animationEnd, the cleanUp function is passed an object containing the class to remove after the animation, the property to replace on the element, and the property value to replace on the element. Check out the DOM before and after clicking button the and you'll see that this works properly.
var el = document.querySelector(".my_element"),
cleanUp = function(data) {
el.classList.remove(data.remove);
el.style[data.prop] = data.val;
},
startAnimation = function() {
el.classList.add("animate");
};
el.addEventListener("animationend", function() {
var cleanup_data = {
remove: "animate",
prop: "opacity",
val: 1
};
cleanUp(cleanup_data);
});
#keyframes foo {
from { opacity: 0; }
to { opacity: 1; }
}
.animate {
animation: foo 3s forwards;
}
.my_element {
opacity: 0;
}
<div class="my_element">some text</div>
<button onclick="startAnimation()">Start Animation</button>
Related
I have a JavaScript function that types out, letter by letter, a message. However, where the current character to be typed is located, I have a blinking css animation. What I need is to stop this animation and make it disappear.
I am using a css with #id::after to put the animation after the text in question. The animation works fine, I need a way to set content: '█'; to content: ''; via JavaScript.
(function type_p(){
let msg = 'This is a message to type out! Spooky!';
let element = document.getElementById('typehere');
typeOut(msg, '', 0, element);
}());
function typeOut(text, letter, index, element){
letter = text.slice(0, ++index);
element.textContent = letter;
if (letter.length == text.length){
stop();
}
setTimeout(typeOut, 100, text, letter, index, element);
}
#typehere {
position: relative;
}
#typehere::after {
content: '█';
position: absolute;
animation: blink 1.5s infinite;
/* animation-iteration-count: 2; */
}
#keyframes blink {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
51% {
opacity: 0;
}
100% {
opacity: 0;
}
}
<p id="typehere">Here</P>
I am aware of CSS animation-iteration-count: however this will stop the animation but it will still be visible (motionless). How do I remove this?
I would just add a class to your element and change the content based on class.
(function type_p(){
let msg = 'This is a message to type out! Spooky!';
let element = document.getElementById('typehere');
typeOut(msg, '', 0, element);
}());
function typeOut(text, letter, index, element){
letter = text.slice(0, ++index);
element.textContent = letter;
if (letter.length == text.length){
element.classList.add('stop');
stop();
}
setTimeout(typeOut, 100, text, letter, index, element);
}
#typehere {
position: relative;
}
#typehere::after {
content: '█';
position: absolute;
animation: blink 1.5s infinite;
/* animation-iteration-count: 2; */
}
#typehere.stop::after {
content: '';
}
#keyframes blink {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
51% {
opacity: 0;
}
100% {
opacity: 0;
}
}
<p id="typehere">Here</P>
This is similar to the other answer, but I find it easier/cleaner than adding multiple classes to something that will no longer be visible.. You can add the animation styling as a class, and then remove that class when you no longer want it to animate.
Change to class in css:
.typehereclass::after {
content: '█';
position: absolute;
animation: blink 1.5s infinite;
}
Add the class to your element in html:
<p id="typehere" class="typehereclass">Here</P>
And then when you want to stop the blinking in JS:
element.classList.remove('typehereclass')
So I want to change the width of a span element inside a h1 element that have the textContent changed every 4s with setInterval().I want to do that to add a transition to the width property to fill the space between the h1 and the next word that span will have smoothly.
I tried to get the width of the span with getBoundingClientRect() but that didn't work and when I set the width it remains the width of the first element and it's not changed dynamically as I would want.
Here is the code:
const changingSpan = document.querySelector('.changing-span');
let array = ['best', 'tastiest', 'freshest'];
let count = 0;
setInterval(function() {
count++;
let elementWidth = changingSpan.getBoundingClientRect().width.toString();
if(count === array.length) count = 0;
changingSpan.classList.add('animation-span');
changingSpan.textContent = array[count];
changingSpan.style.width = `${elementWidth}px`;
changingSpan.addEventListener('animationend', function() {
changingSpan.classList.remove('animation-span');
})
}, 4000);
.changing-span {
display: inline-block;
color: #c82929;
transition: width .2s ease;
}
.animation-span {
animation: moveDown .8s ease;
}
#keyframes moveDown {
0% {opacity: 0;
transform: translateY(-50%);
}
100% {
transform: translateY(0);
}
}
<h1 class="first-heading">The <span class="changing-span">best</span> burgers in town.</h1>
consider an animation using max-width:
const changingSpan = document.querySelector('.changing-span');
let array = ['best', 'tastiest', 'freshest'];
let count = 0;
setInterval(function() {
count++;
if (count === array.length) count = 0;
changingSpan.classList.add('animation-span');
changingSpan.textContent = array[count];
changingSpan.addEventListener('animationend', function() {
changingSpan.classList.remove('animation-span');
})
}, 4000);
.changing-span {
display: inline-block;
color: #c82929;
}
.animation-span {
animation: moveDown .8s ease;
}
#keyframes moveDown {
0% {
opacity: 0;
transform: translateY(-50%);
max-width:0;
}
100% {
transform: translateY(0);
max-width:200px; /* a big value here */
}
}
<h1 class="first-heading">The <span class="changing-span">best</span> burgers in town.</h1>
Your code is very good.
But you need to remove 2 rows like below, then you code works well as you want
let elementWidth = changingSpan.getBoundingClientRect().width.toString();
changingSpan.style.width = ${elementWidth}px;
So the answer was posted by Sean above(Thank you). I will put here the code snippet for this in case somebody will search for something similar and will want to do the same thing:
const changingSpan = document.querySelector('.changing-span');
const changingSpanWrapper = document.querySelector('.changing-span-wrapper');
let array = ['best', 'tastiest', 'freshest'];
let count = 0;
changingSpanWrapper.style.width = `${changingSpan.getBoundingClientRect().width.toString()}px`;
setInterval(function() {
count++;
if(count === array.length) count = 0;
changingSpan.classList.add('animation-span');
changingSpan.textContent = array[count];
changingSpan.addEventListener('animationstart', function() {
let elementWidth = changingSpan.getBoundingClientRect().width.toString();
let elementHeight = changingSpan.getBoundingClientRect().height.toString();
changingSpanWrapper.style.width = `${elementWidth}px`;
changingSpanWrapper.style.height = `${elementHeight}px`;
})
changingSpan.addEventListener('animationend', function() {
changingSpan.classList.remove('animation-span');
})
}, 4000);
.changing-span-wrapper {
display: inline-block;
transition: width .2s ease, height .2s ease;
}
.changing-span {
display: inline-block;
color: #c82929;
}
.animation-span {
animation: moveDown 1s ease;
}
#keyframes moveDown {
0% {opacity: 0;
transform: translateY(-50%);
}
100% {
transform: translateY(0);
}
}
<h1 class="first-heading">The <span class="changing-span-wrapper"><span class="changing-span">best</span></span> burgers in town.</h1>
How can I create the CSS animation below in JavaScript? I've looked all over Google, and tried multiple times to create this but I couldn't figure out how to do this.
#keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 100;
}
}
To run this, I know I can use what is shown below, but I don't know how to create this animation. Can anyone help?
element.style.animation = "fadeIn 5s linear";
You can use javascript with transition to achieve it
// start frame
const start = {
opacity: 0
};
// end frame
const end = {
opacity: 1
};
const element = document.querySelector('span');
Object.assign(element.style, start);
element.style.transition = 'all 5s linear';
requestAnimationFrame(() => {
Object.assign(element.style, end);
});
<span>Lorem Ipsum</span>
What do you mean exactly with "Create in Javascript"? Without using CSS?
If so, you can use a simple interval to update the opacity of the element until it reached 0 or 100. Simple example:
let opacity = 0;
const fadeEl = document.getElementById("fadeInElementIdWithOpacity0");
const fadeInInterval = setInterval(() => {
if (opacity < 1) {
opacity = opacity + 0.1
fadeEl.style.opacity = opacity;
} else {
clearInterval(fadeInInterval);
}
}, 200);
You can first define this function with whatever amount of intervals that you want and then call it with any querySelector
function fadeIn(x) {
var fade = document.querySelector(x);
var opacity = 0;
var intervalID = setInterval(function() {
if (opacity < 1) {
opacity = opacity + 0.1
fade.style.opacity = opacity;
} else {
clearInterval(intervalID);
}
}, 200);
}
havnig this function in console and running fadeIn(".-logo") will fade in the stackoverflow's logo
I have this dive the toggle Hide / Show !! ... It works ok , but I would like to know how to add transition animation to the hide/show ?
this is my JS :
function myFunction() {
var x = document.getElementById("clock1");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none" ;
}
You cannot animate the display property. But you can animate the visibility or opacity property in css easily:
// main.html
<div id="clock1" class="hidden">...</div>
// main.css
#clock1 {
visibility: visible;
opacity: visible;
transition: visibility 0s, opacity 0.5s linear;
}
#clock1.hidden {
visibility: hidden;
opacity: 0;
}
// main.js
function myFunction() {
var x = document.getElementById("clock1")
if (x.classList.contains('hidden')) {
x.classList.remove('hidden')
} else {
x.classList.add('hidden')
}
}
Setting display to none will immediately hide the element, which means there is not opportunity for animation/transition of visibility over time.
Perhaps you could consider using opacity instead, to achieve this?
Add the following CSS:
#clock1 {
transition:opacity 1s;
}
Update your JS:
function myFunction() {
var x = document.getElementById("clock1");
// Update opacity rather than display
if (x.style.opacity === "0") {
x.style.opacity = 1;
} else {
x.style.opacity = 0;
}
}
Working jsFiddle here
I am trying to create my own website, where it has an initial quote in the center:
"Welcome to my website", and when you hover over the menu options, the quote should change.
For example: if I hover over About it could say: "This is my About me Page". (The example is obviously simplified).
HTML Snippet:
About
Contact
Home
<div>
<p>
Welcome to my Website!
</p>
</div>
CSS Snippet:
.fade {
animation: fadein 2s;
}
#keyframes fadein {
from {
opacity:1;
}
50% {
opacity: 0;
}
to {
opacity:1;
}
}
JS Snippet
let myP = document.querySelector('p');
let titleWords = document.querySelector('a.titleAbout');
titleWords.addEventListener('mouseenter', function(){
myP.classList.add("fade");
setTimeout(function(){
myP.innerHTML = "This is my about Me page";
}, 1000);
setTimeout(function(){
text.classList.toggle("fade");
}, 2000);
});
titleWords = document.querySelector('a.titleContact');
titleWords.addEventListener('mouseenter', function(){
myP.classList.add("fade");
setTimeout(function(){
myP.innerHTML = "This is my Contact page";
}, 1000);
setTimeout(function(){
text.classList.toggle("fade");
}, 2000);
});
However - it only does the fade properly the first time I hover over a menu item, the other times it changes the innerHTML, but doesn't fade in and out.
Why exactly is this happening an how can I fix it?
you have not defined the text variable in your javascript. I think you mean myP.classList.toggle("fade");
let myP = document.querySelector('p');
let titleWords = document.querySelector('a.titleAbout');
titleWords.addEventListener('mouseenter', function(){
myP.classList.add("fade");
setTimeout(function(){
myP.innerHTML = "This is my about Me page";
}, 1000);
setTimeout(function(){
myP.classList.toggle("fade");
}, 2000);
});
titleWords = document.querySelector('a.titleContact');
titleWords.addEventListener('mouseenter', function(){
myP.classList.add("fade");
setTimeout(function(){
myP.innerHTML = "This is my Contact page";
}, 1000);
setTimeout(function(){
myP.classList.toggle("fade");
}, 2000);
});
.fade {
animation: fadein 2s;
}
#keyframes fadein {
from {
opacity:1;
}
50% {
opacity: 0;
}
to {
opacity:1;
}
}
About
Contact
Home
<div>
<p>
Welcome to my Website!
</p>
</div>
You can do it shorter and without setTimeout:
let myP = document.querySelector('p');
function show(textToShow){
myP.innerHTML = textToShow;
myP.classList.add("fade");
}
function hide(){
myP.classList.remove("fade");
}
.fade {
animation: fadein 3s;
}
#keyframes fadein {
from {
opacity:1;
}
50% {
opacity: 0;
}
to {
opacity:1;
}
}
About
Contact
Home
<div>
<p>
Welcome to my Website!
</p>
</div>
I have refactored your code to a more generic version, so you can have as many links as you want and do not need to repeat your code. It takes a title attribute from the a tag as text. Maybe this behaves more like you intended, you can play around uncommenting that timeout.
const myPContainer = document.getElementById('pContainer');
const titleWords = document.querySelectorAll('a');
let i;
function attachHandlers(i, elem) {
let timeoutHandle;
const pElem = document.createElement('p');
pElem.innerHTML = elem.getAttribute('title');
myPContainer.appendChild(pElem);
elem.addEventListener('mouseenter', function(){
timeoutHandle = null;
pElem.classList.add("fadein");
});
elem.addEventListener('mouseleave', function(){
// timeoutHandle = setTimeout(() => {
pElem.classList.remove("fadein");
// }, 2000);
});
}
for (i = 0; i < titleWords.length; ++i) {
attachHandlers(i, titleWords[i]);
}
#pContainer {
position: relative;
height: 20px;
}
#pContainer p {
position: absolute;
display: block;
opacity: 0;
}
.fadein {
animation: fadein 2s;
display: block;
}
#keyframes fadein {
from {
opacity: 0;
}
50% {
opacity: 1;
}
to {
opacity: 0;
}
}
About
Contact
Home
<div id="pContainer"></div>