Loop a CSS Animation - javascript

So I've got this nice CSS animation here and I would like it to loop.
I have almost no experience with CSS animations yet sadly and no Idea how to do this.
I'd really appreciate if somebody here could help me out a bit.
Thank you!
HTML
<div id="msg">Weeeeeee</div>
Javascript
$("#msg").click(function() {
var duration = 1400;
$msg = $(this);
$msg.css("-webkit-transform", "scale(2)")
.css("-webkit-transition-timing-function", "ease-out")
.css("-webkit-transition-duration", duration + "ms");
setTimeout(function () {
$msg.css("-webkit-transform", "scale(1)")
.css("-webkit-transition-timing-function", "ease-in")
.css("-webkit-transition-duration", duration + "ms");
}, duration);
});
CSS
#msg { font-size: 40pt; font-weight:bold; text-align:center; line-height: 120pt; }

Praveen's solution should be closer to what you asked for, but I'll provide a solution using CSS3 animations instead of using jQuery to animate transitions. IMO it is easier to maintain and understand:
CSS
#-webkit-keyframes foo {
from {
-webkit-transform:scale(1);
}
to {
-webkit-transform:scale(2);
}
}
Then JS:
$("#msg").click(function() {
var duration = 1400;
$msg = $(this);
//syntax is: animation-name animation-duration[ animation-timing-function][ animation-delay][ animation-iteration-count][ animation-direction]
$msg.css("animation", "foo " + duration + "ms ease infinite alternate");
});
Fiddle
I didn't use the optional animation-delay parameter in the above, the rest should be pretty straightforward. infinite iteration count with alternate direction will execute the animation indefinitely alternating the animation direction from (from to to ) to (to to from) until you call $msg.css("animation", "") to remove the animation.
ps. jQuery 1.8+ will do the prefixing in the JS automatically for you.
Of course, you still have to prefix the CSS to work in non-webkit browsers though. Prefixr should do it.
Fiddle with prefixed CSS.

Encapsulate everything inside setInterval()
var duration = 1400;
$msg = $(this);
setInterval(function(){
$msg.css("-webkit-transform", "scale(2)")
.css("-webkit-transition-timing-function", "ease-out")
.css("-webkit-transition-duration", duration + "ms");
setTimeout(function () {
$msg.css("-webkit-transform", "scale(1)")
.css("-webkit-transition-timing-function", "ease-in")
.css("-webkit-transition-duration", duration + "ms");
}, duration);
}, duration);
Does this help? And yeah, please correct me if I am wrong...

You can use class to trigger infinite animations.
This can be imply done by adding a class.
$('#msg').click(function(){
$(this).addClass('loading');
setTimeout(function(){
$('#msg').removeClass('loading');
},2000);
})
#msg{font-size:30px;}
#msg.loading{ animation:1s showborder linear infinite}
#keyframes showborder{
from{border: 5px solid red}
to{border: 5px solid green}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="msg">Weeeeeee CLICK ME</div>
You can read more about css scroll animation which basically adds animation using class addition method.

Related

Triggering CSS3 Keyframes with javascript multiple times

I am triggering CSS3 Keyframes with javascript but its working for with first call after that any call to that function doesn't animate my div.
Here the Javascript code
function animateShare (imgSrc){
var share = document.getElementById("shareTools");
share.style.animation = "testAnimate 1s ease-in-out 0s"
//shareTools.style.animationPlayState = "running";
}
Sample of the issue (Click red box to preview)
var box = document.getElementById("box");
function animateBox(){
box.style.animation = "box 1s ease-in-out 0s";
}
#box{
background:red;
width:100px;
height:100px;
}
#keyframes box {
50%{width:300px;}
}
<div id='box' onclick='animateBox()'><div>
JSFIDDLE
I want it to animate everytime i call this function.
You can use well known hack: destroy and create element to reset animation.
var box = document.getElementById("box");
function animateBox(){
//destroy and create hack
document.body.removeChild(box);
document.body.appendChild(box);
box.style.animation = "box 1s ease-in-out 0s";
}
#box{
background:red;
width:100px;
height:100px;
}
#keyframes box {
50%{width:300px;}
}
<div id='box' onclick='animateBox()'><div>
In case someone is still interested by this there is another trick that works:
Changing the dataset value to something it has never been, and then use a css matching on that data.
I used this technique when animating the collapsing/uncollapsing of a menu, which of course can happen multiple times. Here's how I did it:
#menu[data-closed^="1"]{
animation:menu_closing;
}
#menu[data-closed^="0"]{
animation:menu_opening;
}
So the animation is based on the first character of the dataset (1 or 0).
Then in the click event that wants to close/open the menu:
var closed = menu_ele.dataset.closed // closed right now
? parseInt( menu_ele.dataset.closed.substr(0,1) )
: 0; // assuming menu is initialized open
var counter = menu_ele.dataset.closed // nb of times the menu was closed or open
? parseInt( menu_ele.dataset.closed.substr(1) )
: 0;
menu_ele.dataset.closed = ''+(1-closed)+(counter+1);
This way the "closed" dataset variable changes like this at every click:
11 (closing for the first time)
02 (reopening for the first time)
13
04
15
06
...
The first digit indicates whether it is currently closed, while all the rest is a counter to make the value new every time.
Think about your code - after first call it does nothing, becouse it already changed animation property of that element.
According to this CSS-Tricks article:
function animateShare (imgSrc){
var share = document.getElementById("shareTools");
share.style.animation = "testAnimate 1s ease-in-out 0s";
shareTools.style.animationPlayState = "paused";
shareTools.style.animationPlayState = "running";
}
add this code in the body section after the element for which the animation is being played-
<script>
document.getElementById('shareTools').addEventListener("animationend", function () {
this.removeAttribute("style");
})
</script>
or if you dont want to remove style attribute ,because you have other css than animation then create a class and add class dynimacally and remove it as above code.
You can reset the animation by just removing the animation property from the styles of the element after the animation has complete - removing the element is unnecessary. In my example, I set the duration in JS, but you could just as easily add an animationend hook to keep it simpler.
JSFiddle
var duration = 1000;
document.getElementById('box').addEventListener('click', function onClick(ev) {
var el = this;
el.style.animation = 'box ' + (duration / 1000 + 's') + ' ease-in-out';
setTimeout(function() {
el.style.animation = ''
}, duration);
});
#box {
background: red;
width: 100px;
height: 100px;
}
#keyframes box {
50% {
width: 300px;
}
}
<div id='box'><div>

Fade in using plain javascript

Trying to do a simple fade in using the opacity property of an h1 element. I'm learning javascript, so would like to try this using plain javascript (yes, I know it is much easier using jQuery).
Pasting only relevant snippets:
<body onload="fadeIn()">
...
<div class = "container">
<div class = "row">
<div class = "col-md-3">
<img class = "img-responsive" src="icons/Website_Logo.png">
</div>
<div class = "col-md-9 page-header">
<h1 id="welcomeHeader" style="opacity:0">
Welcome to the world!
</h1>
</div>
</div>
</div>
...
<script>
function fadeIn() {
var el = document.getElementById("welcomeHeader");
var op = parseFloat(el.style.opacity);
var timer = (function () {
if(op >= 1.0)
clearInterval(timer);
op += 0.1;
el.style.opacity = op;
}, 50);
}
</script>
</body>
Help is much appreciated! Thanks!
jsFIDDLE
You need to call the setInterval function first in order to invoke a timer. Rest is fine. Here is a working fiddle
Code Snippet:
function fadeIn() {
var el = document.getElementById("welcomeHeader");
var op = parseFloat(el.style.opacity);
var timer = setInterval(function () {
console.log('here');
if(op >= 1.0)
clearInterval(timer);
op += 0.1;
el.style.opacity = op;
}, 50);
}
You need to change your function to use setInterval like so:
var timer = setInterval(function () { // notice the setInterval added.
if(op >= 1.0)
clearInterval(timer);
op += 0.1;
el.style.opacity = op;
}, 50);
Notes:
I give you this answer to help you LEARN javascript as you mentioned, otherwise,
it would be better done with pure css of course.
Also, make sure your opacity is set to 0 in your css as a starting point.
You don't need a timer for this - all you need to do is change the class. Here's an example:
the CSS:
element{
/* whatever styles you have */
}
element_faded{
transition: opacity .5s;
opacity: 50%; /* or whatever values you want */
}
the javascript
var element = document.getElementById('element');
// in order to trigger the fade, just change the class
element.className = "element_faded";
In the transition will happen between the values of the original and new class, so if you want a fade-in, have the original opacity be 0% and the new one be 100% or something higher than zero, depending on what you want the final opacity to be. Also, remember that the transition characteristics are determined by the transition attribute in the new class.
Doing this without CSS will just make things more complicated unless you need to do something more sophisticated than just plain fading in or out. If that's the case, then use setInterval or perhaps even something like requestAnimationFrame if you're feeling adventurous.
Honestly, this isn't really the kind of thing you need to learn when first learning javascript. Eventually this will be really easy once you get some confidence under your belt doing things that work more easily in javascript (setTimeout and the like can have their own weird caveats). Try to set a meaningful, practical goal and fulfill it first, using whatever mix of javscript/css/html you can and you'll soon have the basics down well enough to find things like this obvious.

Add a fading effect to inside my JavaScript function

I have a JavaScript function to display images in a slideshow by changing the source. I have tried to create smth to include a fadeIn effect but I think it was catastrophic..Here is my JavaScript function. I don't need a complete answer, just some tips helping me to achieve that. I'm a very beginner in JavaScript but I want to learn it well. If there is a way to do that without jQuery, it would be nice, or to include jQuery directly inside this function will be the best.
{
function nextImage() {
if (currentImage < 5) {
currentImage = currentImage + 1;
} else {
currentImage = 1;
}
document.getElementById('image').src = 'images/' + currentImage + '.jpg';
}
}
Naturally, what the fadein will be adapt as a fadeout in the opposite function, but I think this example can help a newbie like me.
with jquery it would go something like this:
function nextImage() {
if (currentImage < 5) {
currentImage = currentImage + 1;
} else {
currentImage = 1;
}
$("#image").fadeOut('fast', function() {
$("#image").attr('src','images/' + currentImage + '.jpg');
$("#image").fadeIn('fast');
});
}
I don't think it's a stupid question, though for whatever reason my own questions get downvoted, go figure! (end rant)
You might consider if you are able to use CSS there are CSS3 fade transitions that you can try.
If you were to do it in Javascript I would probably use jQuery to do it because those functions are already there and all you have to do is use .show('slow') and .hide('slow') and that argument 'slow' will automatically do the animation for you.
http://api.jquery.com/show/
Otherwise if you want to write it from scratch, then you can probably look at the jQuery source code to see how the actual animation effect is done.
You should JQuery as they have made it very easy to do the effects:
http://api.jquery.com/category/effects/fading/
Take a look at their examples and documentations
Here is an example:
Examples:
Example: Animates hidden divs to fade in one by one, completing each animation within 600 milliseconds.
<!DOCTYPE html>
<html>
<head>
<style>
span { color:red; cursor:pointer; }
div { margin:3px; width:80px; display:none;
height:80px; float:left; }
div#one { background:#f00; }
div#two { background:#0f0; }
div#three { background:#00f; }
</style>
<script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
<span>Click here...</span>
<div id="one"></div>
<div id="two"></div>
<div id="three"></div>
<script>
$(document.body).click(function () {
$("div:hidden:first").fadeIn("slow");
});
</script>
Some tips on how to start using JQuery:
var a = $(document); // <-- set the hole document to variable a
var b = $("#myid"); // <-- set the element that has id="myid" to variable b
var c = $(".myclass"); // <-- set the element(s) that has class="myclass" to variable c
var d = $("img"); // <-- set the img element(s) to variable d
Use Chrome Web Inspector or Firebug to debug your JavaScript code

A JS fade effect doesn't work (for loop)

I tried doing a JS fade effect with the setTimeout() function and it appeared to work to some extent, but I can't seem to figure out what's wrong with the code below:
<html>
<head>
<title></title>
<script type="text/javascript">
function FadeEffect(n)
{
var i=1;
fade = document.getElementById("box");
if (n===1)
{
fade.style.opacity=i/10;
i++;
setTimeout("FadeEffect(1)",50);
if (fade.style.opacity=1)
{
var i=1;
}
}
else if (n===0)
{
fade.style.opacity=1-i/10;
i++;
setTimeout("FadeEffect(0)",50);
if (fade.style.opacity=0)
{
var i=1;
}
}
}
</script>
<style type="text/css">
#box{
width: 200px;
height: 50px;
border: 1px solid black;
background-color: #ccc;
opacity: 0;
}
</style>
</head>
<body>
<div onMouseOver="FadeEffect(1)" onMouseOut="FadeEffect(0)" id="box">Menu</div>
</body>
</html>
Edit: updated the code with setTimeout() functions.
There are two problems with the function that I can see.
First, your if statements both do an assignment rather than a comparison. You are saying if (n=0) (one =, assignment) when you should be saying if (n===0) (three ===, comparison, or you can use two == for a type-converting comparison).
Second, using a for loop to repeatedly change the style isn't going to fade because the browser doesn't update the display at the same time as your code is executing - essentially it uses the same thread for display and for JavaScript. So the page will be updated after the function exits. You need to give the browser a chance to update after each iteration by using setTimeout() - something like:
function fadeEffect(element,startValue,target,delay){
element.style.opacity = startValue;
if (startValue < target)
startValue = Math.min(startValue + 0.1, target);
else
startValue = Math.max(startValue - 0.1, target);
if (startValue != target)
setTimeout(function(){fadeEffect(element,startValue,target,delay);}, delay);
}
<div onMouseOver="fadeEffect(this, 1, 0, 100);"
onMouseOut="fadeEffect(this, 0, 1, 100);" id="box">Menu</div>
Demo: http://jsfiddle.net/hLQ6y/2/
EDIT: Note that this code doesn't cope all that brilliantly if you move the mouse in and out too quickly, i.e., if you trigger the fade in before the fade out has finished. (You can see what I mean in my jsfiddle.) You can solve this by saving the return from .setTimeout() and calling .clearTimeout() if required. Given that I've already covered the essence of the question I'll leave the fine-tuning as an exercise for the reader...
UPDATE: Your updated code has introduced new if statements with the same assignment-instead-of-comparison problem. Also it is calling setTimeout() forever - you should do that conditionally as in the answers Pointy and I gave. Also you seem to be relying on the variable i which, as a local variable, will not retain its value between calls - you could make it a global, but better to manage it as a parameter like I did or as a local variable in an outer function like Pointy did.
The problem is that all those changes to the style will happen before the browser bothers to update the display. What you need to do is space out the changes over a much, much longer period of time using "setTimeout()".
function fadeIn() {
function increment() {
box.style.opacity = Math.min(1.0, (opacity += 0.1));
if (opacity < 1.0) {
setTimeout(increment, 100);
}
}
var box = document.getElementById('box'), opacity = 0;
box.style.opacity = opacity;
setTimeout(increment, 100);
}
edit — Here is a jsfiddle to demonstrate.
If you want it to fade, you need to create a function that sets the opacity -0.1 or +0.1 and then calls itself with setTimeout in 100ms (or fewer). If you don't let the script wait, it will be too fast and immediately set the opacity to 1.0.
Anyways, you could do this a lot easier using jQuery.

How to toggle element visibility without jQuery?

I'm writing an auction template for eBay, hoping that eBay would allow it. Apparently they don't because jquery has things like string.replace() etc.
The code is very basic.
$(document).ready(function(){
function changeImage(){
if($("#coin1").css("display") == "none"){
$("#coin1").fadeIn("slow");
}else{
$("#coin1").fadeOut("slow");
}
};
setInterval ( changeImage, 5000 );
});
I basically need to rewrite it in plain Javascript...
If you can live without the fading effect, it should be pretty straightforward:
function changeImage() {
var image = document.getElementById('coin1');
image.style.display = (image.style.display == 'none') ? 'block' : 'none';
}
setInterval(changeImage, 5000);
While fading is cool and all, it's really makes the code a lot more complicated, when we not allowed to use external libraries. Basically, you will need to deal with additional timers, firing with very short intervals, changing the opacity of the target element on each callback.
If you really want fading, see "Javascript Tutorial - Simple Fade Animation".
The most basic of fading, not cross-browser compatible (try in Chrome):
<div id="x" style="background-color: yellow;">
fade me out
</div>
<script type="text/javascript">
var val = 1.0;
function fade()
{
document.getElementById('x').style.opacity = val;
val -= 0.1;
if (val != 0)
{
setInterval(fade, 100);
}
}
</script>
You could use classList.toggle on your element:
<style>
.hidden { display: none !important; }
</style>
<script>
function toggle() {
document.getElementById('elem').classList.toggle('hidden');
}
</script>
Toggle element
<p id="elem">lorem ipsum quid modo tralala</p>
I had issues with the interval approach. This is what I came up with.
function showHide() {
var element = document.getElementById('hiddenDetails');
element.classList.toggle("hidden");
}
.hidden {
display: none;
}
.show {
display: block;
}
Get Details
<div id="hiddenDetails" class="hidden">What you want to show and hide</div>

Categories