Button text transition with pure Javascript - javascript

I have a fade in function made with pure javascript as this site shows.
function fadeIn(el) {
var opacity = 0;
el.style.opacity = 0;
el.style.filter = '';
var last = +new Date();
var tick = function() {
opacity += (new Date() - last) / 400;
el.style.opacity = opacity;
el.style.filter = 'alpha(opacity=' + (100 * opacity)|0 + ')';
last = +new Date();
if (opacity < 1) {
(window.requestAnimationFrame && requestAnimationFrame(tick)) || setTimeout(tick, 16);
}
};
tick();
}
What I need is to apply this transition in a change of button text, something like:
var firstChild = document.getElementById('my-button').firstChild;
firstChild.data = 'Another text';
fadeIn(firstChild);
Of course this do not works as expected, but I wanted something to achieve a behavior that on a change text, a fade in transition is triggered only to the text, not to the entire button.
Is there a way to achieve this?

Since you're using firstChild i assume your text is inside a child element of the button element, if that is the case, this will work.
Click the blue "run code snippet" button at the bottom to see it in action.
btn.addEventListener('click', function(){fadeOut(this.firstChild, newText)});
var newText = "World!";
function fadeOut(e, nT) {
o=1;
t=setInterval(function () {
if(o <= 0.1){
clearInterval(t);
e.style.filter = "alpha(opacity=0)";
if(nT != undefined) {
e.innerHTML = nT;
fadeIn(e);
}
}
e.style.opacity = o;
e.style.filter = 'alpha(opacity='+o*100+")";
o-=o*0.05;
}, 10);
}
function fadeIn(e) {
o=0;
t=setInterval(function () {
if(o >= 0.9){
clearInterval(t);
e.style.filter = "alpha(opacity=1)";
}
e.style.opacity = o;
e.style.filter = 'alpha(opacity='+o*100+")";
o+=0.05;
}, 25);
}
#btn {
color: Black;
width: 100px;
border: 1px solid black;
}
<button id="btn"><p>hello</p></button>

To change the text colour, using this function, you can set it's colour using RGBA - the A stands for the alpha channel.
So, something like this:
el.style.color = "rgba(0,0,0, "+ OPACITY +")" // Opacity is 0 - 1
You could also make your code more modular, allowing you to edit any style property with this fade function.
function fadeIn(el,prop,color) {
var opacity = 0;
el.style[prop] = 0;
var last = +new Date();
var tick = function() {
opacity += (new Date() - last) / 400;
el.style[prop] = "rgba("+color+","+opacity+")";
last = +new Date();
if (opacity < 1) {
(window.requestAnimationFrame && requestAnimationFrame(tick)) || setTimeout(tick, 16);
}
};
tick();
}
now you could do both:
fadeIn(firstChild,"background", "255,0,0"); // fade in background to red
fadeIn(firstChild,"color", "0,0,0"); // fade in text to black

Related

setInterval to fade in then fade out pure javascript no jquery or css

I am trying to implement a fade in/fade out feature that runs on a button click depending if some data was changed. I am using angular but the ngAnimate I could not get to work so I want to do it with pure js. What I currently have will flash the text for a second, then do nothing. This is inside my controller.
var warningText = document.getElementById('warningText');
warningText.style.display = 'inline'
$scope.warningText = "Warning: No Data was updated.";
var op = 0.0;
var fadeIn = setInterval(function() {
if (op >= 1) {
clearInterval(fadeIn);
fadeOut(op);
}
warningText.style.opacity = op;
op += op * 0.1;
}, 50);
var fadeOut = function(op) {
setInterval(function() {
if (op <= 0.1) {
clearInterval(fadeOut);
warningText.style.display = 'none';
}
warningText.style.opacity = op;
op -= op * 0.1;
}, 50);
}
Your calculation of op is wrong as that will always be zero. Secondly the second function does not return the value from setInterval, so you'll never be able to clear that interval.
Here is how you could do it with just one interval, where the sign of the increments to the opacity is reversed every time the boundary value is reached:
var warningText = document.getElementById('warningText');
function flickerMessage(msg) {
var op = 0.1;
var increment = +0.1;
warningText.textContent = msg;
warningText.style.opacity = 0;
warningText.style.display = 'inline';
var timer = setInterval(function() {
op += increment;
warningText.style.opacity = op;
if (op >= 1) increment = -increment;
if (op <= 0) {
warningText.style.display = 'none';
clearInterval(timer); // end
}
}, 50);
}
flickerMessage('Warning you');
<div id="warningText" style="display:none; opacity: 0">warning text</div>
<hr>

JavaScript image fade out and in (using only JavaScript, no jQuery)

I am trying to make an image to fade out and then in. The problem is that when I use two functions, the image doesn't fade out but it immediately disappears. Is there anyone with amazing JavaScript skills to solve my problem?
Please do not tell me about jQuery because I already know how to do it using it, I only need to improve my JavaScript skills.
PS: I need also to understand why it doesn't work and how to make it work with as much details please.
Here is my code:
var el = document.getElementById("img1");
el.addEventListener("click", function() {
function fadeOut() {
el.style.opacity = 1;
function fade(){
var val = el.style.opacity;
if ((val -= .01) > 0){
el.style.opacity = val;
requestAnimationFrame(fade);
}
}
fade();
};
function fadeIn() {
el.style.opacity = 0;
function fade1() {
var val = el.style.opacity;
if ((val += .01) < 1){
el.style.opacity = val;
requestAnimationFrame(fade1);
}
}
fade1();
};
fadeIn();
fadeOut();
});
Thank you!
Still not the prettiest, but I have made just the minimum changes to your code to make it work: http://codepen.io/rlouie/pen/BzjZmK
First, you're assigning the opacity value back and forth repeatedly for no reason, which makes the code confusing to follow and also results in string concatenation instead of addition or subtraction, I have simplified this. Second, the functions were named the opposite of what they did, also confusing and fixed by me here. Finally, you ran both functions one after the other, so the second function set opacity to zero and then broke. Instead, I use a promise in your first function and resolve it when the animation completes.
That way the second function does not run until after the first one has completed animating.
var el = document.getElementById("img1");
el.addEventListener("click", function() {
function fadeOut() {
return new Promise(function (resolve, reject) {
let opacity = 1;
function fade(){
if ((opacity -= .01) > 0){
el.style.opacity = opacity;
requestAnimationFrame(fade);
} else {
resolve();
}
}
fade();
});
};
function fadeIn() {
let opacity = 0;
function fade1() {
if ((opacity += .01) < 1){
el.style.opacity = opacity;
requestAnimationFrame(fade1);
}
}
fade1();
};
fadeOut().then(fadeIn);
});
My proposal is:
start animation with fadein
when fadein finishes start the fadeout
var el = null;
function fadeIn(timestamp) {
var val = (+el.style.opacity == 0) ? 1 : +el.style.opacity;
if ((val -= .005) > 0) {
el.style.opacity = val;
window.requestAnimationFrame(fadeIn);
} else {
window.requestAnimationFrame(fadeOut);
}
}
function fadeOut(timestamp) {
var val = (+el.style.opacity == 0) ? 1 : +el.style.opacity;
if ((val += .005) < 1) {
el.style.opacity = val;
window.requestAnimationFrame(fadeOut);
}
};
window.onload = function () {
el = document.getElementById('img1');
el.addEventListener('click', function(e) {
window.requestAnimationFrame(fadeIn);
});
}
<img id="img1" src="http://www.loc.gov/pictures/static/data/highsm/banner.jpg">
Voor de fade in:
Function FadeIn() {
var milli = 3000; //duration
el = yourelement;
el.style.opacity = 1;
var a = 1 / (milli / 1000 * 16); //the -x
FadeIn_loop(a);
}
Function FadeIn_loop(a) {
if (el.style.opacity > 0.01) {
el.style.opacity = el.style.opacity - a;
setTimeout("FadeIn(" + el + ")", 16); //about 1/60 a second
} else {
el.style.opacity = 0;
}
}
Same thing for fade out, succes!
In your code are many things that does'nt seem to be right. First of get all those functions out of each other otherwise requestAnimationframe cant find the functions.

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>

Javascript div fade in not working using setInterval

I'm trying to make a div containing a number of pictures to fade in but its not working and I don't know why. I believe that the inverval is not even being called. The div's opacity is set to 0.0 This is the code:
var movies = getElementById("movies");
var apparence = function(){
if(movies.style.opacity < 1.0){
movies.style.opacity = movies.style.opacity + 0.1;
} else { clearInterval(timer);
}
}
var timer = window.setInterval(apparence, 1000);
Thank you very much.
To set your movies var, you need to call:
document.getElementById('movies');
The way you are attempting to increment opacity didn't work, so I've updated your example.
New Code:
var movies = document.getElementById("movies");
var opacity = 0.1;
var apparence = function(){
if(opacity <= 1.0) {
movies.style.opacity = opacity;
} else {
clearInterval(timer);
}
opacity += 0.1;
}
var timer = window.setInterval(apparence, 1000);
JS Fiddle:
http://jsfiddle.net/onov6cq4/1/
Here is your problem
Problem1:
If you have defined your css using
#movies {
opacity: 0.0;
}
then document.getElementById().style.opacity is empty since it takes from inline style i.e. <div id="movies" style="opacity: 0.0">
Problem 2:
movies.style.opacity = movies.style.opacity + 0.1;
movies.style.opacity returns a string so you are basically appending string which results in 0.10.1 and so on. You need to do parseFloat! The attached fiddle will solve your problem
Code:
var moviesOp = document.getElementById('movies').style.opacity;
function apparence(){
console.log('interval called with op = ' + moviesOp);
if(moviesOp < 1.0){
moviesOp = parseFloat(moviesOp, 10) + 0.1;
} else {
clearInterval(timer);
}
}
var timer = setInterval(apparence, 1000);
<div id="movies" style="opacity: 0.0">
JSBin With Inline Style
If you want to use in css and not inline then use getComputedStyle. This i tried and works as u wanted
var movies = document.getElementById('movies');
function apparence(){
var moviesOp = getComputedStyle(movies).getPropertyValue('opacity');
console.log('interval called with op = ' + moviesOp);
if(moviesOp < 1.0){
movies.style.opacity = parseFloat(moviesOp, 10) + 0.1;
} else {
clearInterval(timer);
}
}
var timer = setInterval(apparence, 1000);
Non Inline jsBin

Create infinite loop with moving divs using javascript or jQuery

I need to simulate a band that moves from left to right continuously, carrying 15 divs on it and moving them in a circle, like a carousel. When they reach the right margin to appear from the left.
I have the code that works for 1 div(more or less), but Im having troubles making the loop that includes all 15 divs.
What am I missing?
Here's what I have so far:
HTML
<body>
<div id="fooObject0">1</div>
<div id="fooObject1">2</div>
....
<div id="fooObject13">14</div>
<div id="fooObject14">15</div>
</body>
CSS
body {
font:76% normal verdana,arial,tahoma;
width:600px;
height:600px;
position:relative;
margin:0 auto;
border:1px solid;
}
div {
position:absolute;
left:0px;
top:8em;
width:55px;
height:70px;
line-height:3em;
background:#99ccff;
border:1px solid #003366;
white-space:nowrap;
padding:0.5em;
}
javascript
var foo = null; // object
function doMove(id) {
foo = document.getElementById(id);
foo.style.left = parseInt(foo.style.left)+1+'px';
setTimeout(doMove(id),20); // call doMove in 20msec
if(foo.style.left == "600px") {
foo.style.left = 0;
}
}
function init() {
for(i=0;i<15;i++){
var foo = document.getElementById('fooObject' + i); // get the "foo" object
foo.style.left = -i*55+'px'; // set its initial position to 0px
doMove('fooObject' + i); // start animating
console.log('fooObject' + i);
}
}
window.onload = init;
Thank you in advance!
It call an invalid function setTimeout(doMove(id), 20);.
doMove(id) return undefined, or you use "shared var" (Orientad Object) or doMove need return other function.
Note: var foo = null; // object this variable causes conflict when using setTimeout or setInterval
Try this (read my comments in code):
function doMove(id) {
return function() {
var foo = document.getElementById(id);//Global variable causes conflict when using `setTimeout` or `setInterval`
foo.style.left = parseInt(foo.style.left)+1+'px';
setTimeout(doMove(id),20); //setTimeout need an valid function
if(foo.style.left == "600px") {
foo.style.left = 0;
}
}
}
function init() {
for(i=0;i<15;i++){
var foo = document.getElementById('fooObject' + i);
foo.style.left = -i*55+'px';
doMove('fooObject' + i)(); //doMove need "()", because not run "direct"
console.log('fooObject' + i);
}
}
I modified the code for effect "carousel" and fix the problem with "left" (In 1 to 5 div):
function carrousel() {
var numberOfItems = 15; //Change this if needed
var delay = 1; //Change delay time if needed
var limitArea = 599; //Size limit your carousel area (600px, used 599 for limit with `>`)
var sizeObject = 58; //Width size of objects
//Don't change
var index = 0; //Current index
var allItems = []; //Indexed objects
//Get and index all objects
for(index = 0; index < numberOfItems; index++){//user var
allItems[index] = document.getElementById("fooObject" + index);
}
//Convert position left for int and detect "NaN"
var getPosition = function(pos) {
pos = parseInt(pos);
if (isNaN(pos)) {
return parseInt(-(index * sizeObject));
} else {
return parseInt(pos + 1);
}
};
var doMoveAll = function() {
var foo, post;
for(index = 0; index < numberOfItems; index++){//user var
foo = allItems[index];//Current object
pos = getPosition(foo.style.left);//Get position
//Detect if object are in out area
if(pos > limitArea) {
var beforeItem;
//Get before object for effect carousel
switch(index + 1) {
case 1:
beforeItem = "fooObject" + (numberOfItems - 1);
break;
default:
beforeItem = "fooObject" + (index - 1);
}
//Get position again, but used before object
pos = (
getPosition(document.getElementById(beforeItem).style.left) - sizeObject
);
foo.style.left = pos + "px";
} else {
foo.style.left = pos + "px";
}
}
//Timeout delay
window.setTimeout(doMoveAll, delay);
};
doMoveAll();//Init
};
window.onload = carrousel;

Categories