JavaScript help in animation - javascript

"I want disable fade-in and fade-out animation after one time its apply on whole web page"
I need a pure JavaScript code which disable fade-in and fade-out animation after it apply one time
.fade {
/* transition: opacity 0.9s ease-in;*/
opacity: 0;
}
.fade.visible {
transition: opacity 1s ease-in;
opacity: 1;
}
window.addEventListener('scroll', fade);
function fade()
{
let animation=document.querySelectorAll('.fade');
for (let i=0; i<animation.length; i++)
{
let windowheight=window.innerHeight;
let top=animation[i].getBoundingClientRect().top;
if (top < windowheight)
{
animation[i].classList.add('visible');
}
else
{
animation[i].classList.remove('visible');
}
}
}

Use a count variable. When the function that involves the fade-in and fade-out is triggered, add to the count variable. After it is increased, make it so these changes do not occur any more.
let count = 0;
count++;
If you want to have more code in the answer, post some more from your specific example.

This creates a count variable. If you want the animation to occur exactly once, then this should work as the count is increased by one after the animation occurs, making sure it will not happen again.
let count = 0;
window.addEventListener('scroll', fade);
function fade()
{
if (count < 1)
{
let animation=document.querySelectorAll('.fade');
for (let i=0; i<animation.length; i++)
{
let windowheight=window.innerHeight;
let top=animation[i].getBoundingClientRect().top;
if (top < windowheight)
{
animation[i].classList.add('visible');
}
else
{
animation[i].classList.remove('visible');
}
}
}
else
{
return;
}
count++;
}

Related

How would I apply a fade out animation to each of the icons in my menu within a for loop

im currently working on an animation where there's a delay between each of the icons when fading out. The fade out animation works fine, but only on the first icon and im unsure on why this is. Could some one maybe point out the mistake im making?
Javascript code:
function closeHorizontalWindow()
{
const delay = 150;
const reasons = ['btnReady', 'btnNotReady', 'btnBreak', 'btnEmail', 'btnLunch',
'btnComfortBreak', 'btnMeeting', 'btnChat']
for (let i = 0; i < reasons.length; i++) {
document.getElementById(reasons[i]).style.animation = `reasonsfadeout 0.45s ease-out
forwards ${delay}ms`
delay+=150
}
CSS code:
#keyframes reasonsfadeout
{
from{opacity: 1; }
to {opacity: 0; }
}
}
Thankyou
You can use an interval to iterate instead of a regular for-loop.
function closeHorizontalWindow()
{
const delay = 150;
const reasons = ['btnReady', 'btnNotReady', 'btnBreak', 'btnEmail', 'btnLunch',
'btnComfortBreak', 'btnMeeting', 'btnChat']
let i = 0;
const interval = setInterval(function(){
document.getElementById(reasons[i]).style.animation = `reasonsfadeout 0.45s ease-out forwards ${delay}ms`;
i++;
if(i>=reasons.length){
clearInterval(interval);
}
}, delay);
}

Change colour for short period of time JavaScript & CSS

I'm doing simple ID validating html page with javascript. My idea is, whenever user enters a valid ID number, the text field of form changes its colour for few seconds and then revert back to normal.
the code
<script>
var abcArray = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];
var IDweights = [7,3,1,0,7,3,1,7,3];
var valuesMap = new Map();
for(var i=0;i<26;i++){
valuesMap.set(abcArray[i],i+10);
}
validateID();
function validateID(){
var idNumber = document.forms.form.idnum.value.toUpperCase();
var sumOfValues = 0;
for(var x = 0; x < idNumber.length; x++){
if(x < 3){
sumOfValues += (valuesMap.get(idNumber.charAt(x))*IDweights[x]);
}
if(x > 3){
sumOfValues += (parseInt(idNumber.charAt(x))*IDweights[x]);
}
}
if(sumOfValues % 10 == idNumber[3]){
var y = document.getElementById("idnum");
y.style.animation = "anim 5s"; // when true change to green
} else {
var y = document.getElementById("idnum");
y.style.animation = "anim1 5s"; //change to red
}
}
the css part
#-webkit-keyframes anim {
0% {background:white;}
20% {background:green;}
100% {background:white;}
}
#-moz-keyframes anim {
0% {background:white;}
20% {background:green;}
100% {background:white;}
}
#-webkit-keyframes anim1 {
0% {background:white;}
20% {background:red;}
100% {background:white;}
}
#-moz-keyframes anim1 {
0% {background:white;}
20% {background:red;}
100% {background:white;}
}
It works but only once. When I click validate button again, then nothing happens. Only when I change ID number for the wrong one, then it works but only once as well, and then again to make it work you need to put the correct one... I am aware it's probably because I'm setting css properties once and thats it, the browser will not change them again if they're the same. But I can't think of proper solution because I'm new to JS and css. I searched for quite long and still didn't find any solution for my problem, partly because I don't really know how to specify it. I'll be grateful for your help.
PS. please only pure js and css - I'am not familiar with jquery yet
the problem is, if the element already has the style="anim1 5s" for example - setting it to that same value again will do nothing. You would need to remove that style, and then add it again.
Better still, when you add the style, add an animationend event listener to that element to remove that animation when the animation completes
function validateID() {
var doneAnimating = function(e) {
// remove the listener
this.removeEventListener('animationend', doneAnimating);
// remove the animate style
this.style.animate = '';
}
var idNumber = document.forms.form.idnum.value.toUpperCase();
var sumOfValues = 0;
for (var x = 0; x < idNumber.length; x++) {
if (x < 3) {
sumOfValues += (valuesMap.get(idNumber.charAt(x)) * IDweights[x]);
}
if (x > 3) {
sumOfValues += (parseInt(idNumber.charAt(x)) * IDweights[x]);
}
}
// moved outside of if/then to tidy up code
var y = document.getElementById("idnum");
// add the listener to the element
y.addEventListener('animationend', doneAnimating);
if (sumOfValues % 10 == idNumber[3]) {
y.style.animation = "anim 5s"; // when true change to green
} else {
y.style.animation = "anim1 5s"; //change to red
}
}
Alternatively, you could simply (outside of this code) add the animationend event listener once, and the doneAnimating can simply remove the animate style and not worry about removing the event listener - in fact you can put the event handler inline to make it very simple
// this is done once only - not sure where in your code you'd put it
document.getElementById("idnum").addEventListener('animationend', function(e) {
this.style.animate = '';
});
function validateID() {
var idNumber = document.forms.form.idnum.value.toUpperCase();
var sumOfValues = 0;
for (var x = 0; x < idNumber.length; x++) {
if (x < 3) {
sumOfValues += (valuesMap.get(idNumber.charAt(x)) * IDweights[x]);
}
if (x > 3) {
sumOfValues += (parseInt(idNumber.charAt(x)) * IDweights[x]);
}
}
// moved outside of if/then to tidy up code
var y = document.getElementById("idnum");
if (sumOfValues % 10 == idNumber[3]) {
y.style.animation = "anim 5s"; // when true change to green
} else {
y.style.animation = "anim1 5s"; //change to red
}
}

How to fade in and out one by one using css animation and angular?

Consider the following plunker
I have a list of tile that I want to fade in one by one using ng-repeat however the animation fade the entire tile set all together.
Here is my CSS
.fade-up {
animation: fadeUpIn 5s ease-in-out;
}
.fade-in {
animation: fadeUpOut 5s ease-in-out;
}
#keyframes fadeUpIn {
0% {
opacity: 0;
transform: translate3d(0, 100%, 0);
}
100% {
opacity: 1;
transform: none;
}
}
Here is my template:
<div ng-controller="baseController as bCtrl">
<button ng-click="bCtrl.toggleStuff()">
Toggle
</button>
<div ng-repeat="group in bCtrl.groupList">
<div class="tile-style"
ng-repeat="tile in group"
ng-class="{'fade-up': bCtrl.display, 'fade-in': !bCtrl.display}">
{{tile}}
</div>
</div>
</div>
Here is my JS
function toggleStuff() {
self.display = !self.display;
}
Is there a way to fade in the tiles individually?
u want it animate one by one, an easy way is to set them to display one by one, custom ng-animate might cost more
u may need to record timeouts and clear when change happen during loop
for (var i = 0; i < 10; i++) {
(function(a) {
setTimeout(function() {
console.log(a); //0,1,2...
//$scope.list[a].display = false;
//$scope.$apply()
}, i * 1000);
})(i)
}
As the other answer suggests, you could do this adding timeouts.
I have applied the solution in your plunker.
http://plnkr.co/edit/RV6E20IP5VLrMDKkOr4G?p=preview
for (var i = 1; i < 26; i++) {
tile = { val: i , display: false };
if (i % 4 == 0){
tempList.push(tile);
self.groupList.push(tempList);
tempList = []
} else {
tempList.push(tile);
}
(function(index, tile) {
$timeout(function() {
tile.display = true;
}, i * 400);
})(i, tile);
}

fadeIn and fadeOut in javascript

I'm trying to write my own animations using JavaScript.
I wrote a function for fadeIn() as below, it changes the display property followed by a change in value of opacity. But it doesn't seem to be working.
What am I doing wrong?
function fadeIn(obj, defDisp) {
obj.style.opacity = 0;
obj.style.display = defDisp;
var opVal = 0;
while (opVal < 1) {
obj.style.opacity = opVal;
opVal += 0.1;
}
}
defDisp = Default value for display property
Without a timing interval, this will likely execute too fast for you to see it. The while loop, without a timeout feature, will execute in far less than a second, and you won't see it happen. It's like asking a computer to count to 10, it will do it in less than a millisecond.
Try using a setTimeout
http://www.w3schools.com/jsref/met_win_settimeout.asp
while(opVal < 1) {
setTimeout(function(){
obj.style.opacity = opVal;
opVal += 0.1;
}, 3000);
}
Alter the timer (3000 in this case) to something that makes your fade work for you. Every 1000 is a one second and your loop runs 10 times, so in this case it would be 30 seconds, likely too slow.
I would probably stick with a CSS transition however, as they tend to render better on all browsers.
var el = document.getElementById('fadein');
fadeIn(el);
function fadeIn(ele, defDisp) {
ele.style.opacity = 0;
ele.style.display = defDisp;
var opVal = 0;
var t = setInterval(function(){
if(opVal >= 1){
clearInterval(t);
}
ele.style.opacity = opVal;
opVal += 0.1;
}, 100);
}
#fadein{ background: #ccc; border:1px solid #ddd; padding: 10px }
<div id="fadein">Hello</div>
Use a function that calls itself after a delay.
function fadeIn(obj, defDisp) {
obj.style.opacity = 0;
obj.style.display = defDisp;
var last = +new Date(); // Keep track of the time to calculate the opacity
var fadeStep = function () {
obj.style.opacity = +obj.style.opacity + (new Date() - last) / 800;
last = +new Date();
if (+obj.style.opacity < 1) {
setTimeout(fadeStep, 16);
}
};
fadeStep();
}
var el = document.getElementById('box');
fadeIn(el, 'block');
#box{ padding: 1em; background: #009afd; color: #ffffff; display: none; }
<div id="box">Hello</div>
If you want the fade to be faster, replace 800 by anything lower and vice-versa.
Because html render and for loop use the same thread, so when you doing the for-loop,you can't see any changes until the function complete. You have to use a setTimeout or setInterval (or requestAnimationFrame which is introduced from html5) so you browser can have the control to change the properties on the page:
You can see a example from the snippet, although the second that use a setTimeout is faster than the first one, which use for loop, the first one will not change its color as browser not able to change color during for-loop.
And if you choose to use requestAnimationFrame like I do in the snippets, you can have a smooth animation while the time can also be controlled precisely.
function fadeIn() {
this.style.opacity = 0;
this.style.display = 'block';
var opVal = 0;
console.time("count");
while(opVal < 1) {
this.style.opacity = opVal;
opVal += 0.000001;
}
console.timeEnd("count");
}
// Accept target as the target to apply anim, time is total anim time in ms.
function fadeInAlt(target, time) {
var opacity = 0;
var last = window.performance.now();
console.time("count2");
target.style.opacity = opacity;
target.style.display = 'block';
var fadeInFunc = function(timeStamp) {
if (opacity < 1) {
// Define the change by passed time.
var timePassed = timeStamp - last;
opacity += timePassed / time;
target.style.opacity = opacity;
last = timeStamp;
requestAnimationFrame(fadeInFunc);
} else {
console.timeEnd("count2");
return;
}
};
requestAnimationFrame(fadeInFunc);
}
var div = document.getElementById('test');
div.onclick = fadeIn;
var div2 = document.getElementById('test2');
div2.onclick = function() {
fadeInAlt(this, 3000);
};
#test {
background-color: red;
width: 30px;
height:30px;
}
#test2 {
background-color: blue;
width: 30px;
height:30px;
}
<div id="test"></div>
<div id="test2"></div>

Punctuation loading "animation", javascript?

I'm looking for a good way to display some punctuation loading "animation".
What I want is something like this:
This will display at second 1: "Waiting for your input."
This will display at second 2: "Waiting for your input.."
This will display at second 3: "Waiting for your input..."
This will display at second 4: "Waiting for your input...."
This will display at second 5: "Waiting for your input."
This will display at second 6: "Waiting for your input.."
This will display at second 7: "Waiting for your input..."
This will display at second 8: "Waiting for your input...."
And so on.
I started by surrounding the dots in spans and thought I could loop through them with jquery and display one more, one more, one more, then reset to 1. But the code got very clumsy, so I wonder how you would do this?
Pure CSS solution
Demo: jsfiddle.net/feklee/D59P9
HTML:
Waiting<span class="dots"><span>.</span><span>.</span><span>.</span></span> for more.
CSS:
#keyframes dots-1 { from { opacity: 0; } 25% { opacity: 1; } }
#keyframes dots-2 { from { opacity: 0; } 50% { opacity: 1; } }
#keyframes dots-3 { from { opacity: 0; } 75% { opacity: 1; } }
#-webkit-keyframes dots-1 { from { opacity: 0; } 25% { opacity: 1; } }
#-webkit-keyframes dots-2 { from { opacity: 0; } 50% { opacity: 1; } }
#-webkit-keyframes dots-3 { from { opacity: 0; } 75% { opacity: 1; } }
.dots span {
animation: dots-1 1s infinite steps(1);
-webkit-animation: dots-1 1s infinite steps(1);
}
.dots span:first-child + span {
animation-name: dots-2;
-webkit-animation-name: dots-2;
}
.dots span:first-child + span + span {
animation-name: dots-3;
-webkit-animation-name: dots-3;
}
WebKit-only alternative
Advantage: No nested tags. This means that the ellipsis could be put as content
into an ::after pseudo element.
Demo: jsfiddle.net/feklee/vFT7W
HTML:
Waiting<span>...</span> for more.
CSS:
body {
font-family: 'Roboto', sans-serif;
font-size: 50px;
}
#-webkit-keyframes dots {
0% { background-position: 0px; }
100% { background-position: 50px; }
}
span {
background: linear-gradient(to right, white 50%, black 50%);
color: transparent;
-webkit-background-clip: text;
-webkit-animation: dots 1s infinite steps(4);
padding-right: 40px;
margin-right: -40px;
}
The trick to making a string of dots is to make a sparse Array and then join all the elements with the desired character.
var count = 0;
setInterval(function(){
count++;
var dots = new Array(count % 10).join('.');
document.getElementById('loadingtext').innerHTML = "Waiting for your input." + dots;
}, 1000);
Here is a Live demo.
This can be very easy:
HTML
<span class="dots"></span>
JQuery
setInterval(function() {
var th = $('.dots');
if(th.text().length < 5){
th.text(th.text()+".");
}else{
th.text("");
}
}, 500);
Demo
Now sure how the code got out of hand, you could just do:
setInterval(function () {
var span = $("#text-loader").children("span:eq(0)");
var ellipsis = span.html();
ellipsis = ellipsis + ".";
if (ellipsis.length > 5) {
ellipsis = ".";
}
span.html(ellipsis);
}, 1000);
<div id="text-loader">
This will display at second 1: "Waiting for your input<span>.</span>
</div>
And as for the 1, you can swap that out with the number of periods.
try this function: i'v put an example here http://jsfiddle.net/XFd39/
var i=0;
function f() {
if(i<=4)
$('#a').append(".");
i++;
if(i==4){
$('#a').html("");
i=0;
}
setTimeout(f,500);
}
f();
Here is a pretty simple variant: http://jsfiddle.net/psycketom/FusdC/
Read the comments below to understand what everything is doing there.
var span = $('.dots'); // take the element where you have the maximum count of dots
var text = span.text(); // cahce it's text value
// we set up a function here, so we can loop it all the time
var loading = function()
{
$({
count : 1 // we start at one dot
}).animate({
count : text.length // together forming all of it
}, {
duration : 1000, // make the animation complete in one second
step : function() {
span.text( text.substring(0, Math.round(this.count)) ); // on each step, change the text accordingly to current iteration
},
complete : function() {
loading(); // once complete, start all over again
}
});
};
loading(); // start it up for the first time
Here you also gain the advantage of using easing if you wish, easily changing total duration and bunch of other benefits in case you're good with jQuery.
Dude, unless you want to display this animation forever you will need a way to stop the animation, or?
Don't even think about global variables, this is JavaScript and it's got closures for that :)
<p>please wait<span id="wait"></span></p>
<input type="submit" id="start" value="start">
<input type="submit" id="stop" value="stop">
<script type="text/javascript">
$(document).ready(function() {
var animator = function($el) {
var dotCount = 1;
var started = true;
return {
"start" : function step() {
dotCount = (dotCount + 1) % 10;
$el.text(new Array(dotCount).join('.'));
if (started) {
setTimeout(step, 100);
}
},
"stop" : function() {
started = false;
}
}
};
var animatedWait = animator($("#wait"));
$("#start").click(animatedWait.start);
$("#stop").click(animatedWait.stop);
});
</script>
Here is a modified version that will turn off the dots after a time.
var count = 0;
var dots = setInterval(function(){
count++;
document.getElementById('loadingtext').innerHTML = "Waiting for your input." + new Array(count % 5).join('.');
if (count == 10){ // show two iterations of the array.
clearInterval(dots); // stop the dots.
}
}, 100); // sets the speed
http://jsfiddle.net/Ty4gt/331/

Categories