I'm writing a fadeIn function for an HTMLElement, the animation works but it's a bit choppy at the moment. what it does is animate a fadeIn from 0 opacity to 1, it also animates over a duration using requestFrameAnimation that's why it's probably so choppy, can someone help me make my animation run more smoothly. and example is on codepen.io look at the header fadeIn and see what I mean
fadeIn: function(duration) {
var el = this.$el,
duration,
end = 0;
el.style.opacity = 0;
el.style.display = "block";
var step = function() {
var current = +new Date(),
remaining = end - current;
if(remaining < 60) {
if(el) {
end = current + duration;
var val = parseFloat(el.style.opacity);
if (!((val += .1) > 1)) {
el.style.opacity = val;
}
} else {
return;
}
}
requestAnimationFrame(step);
};
step();
},
The smoothest one you can do is using CSS transition. But if you want to do with pure Javascript, you can do something like this
function fadeIn(dom, duration) {
let start = null;
const step = (end) => {
if (start === null) start = end;
let dt = end - start;
dom.style.opacity = Math.min(1, dt / duration);
if (dt < duration) requestAnimationFrame(step);
}
requestAnimationFrame(step);
}
function fadeOut(dom, duration) {
let start = null;
const step = (end) => {
if (start === null) start = end;
let dt = end - start;
dom.style.opacity = Math.max(0, 1 - dt / duration);
if (dt < duration) requestAnimationFrame(step);
}
requestAnimationFrame(step);
}
fadeIn(document.getElementById('your_dom'), 2000);
Related
The problem is that It calls the var intervalLeft and intervaRight at the same time. When it is moving right I want the intervalLeft not to work & vice versa.
When It reaches startPosition 100 it activates the intervalLeft and when it reaches startPosition 0 it activates intervalRight infinite.
<div id="moveAnimation" class="block"></div>
</div>
<script>
var elem = document.getElementById("moveAnimation");
elem.addEventListener("click", movingImage);
function movingImage() {
var startPosition = 0;
var intervalRight = setInterval(frameRight, 10);
var intervalLeft = setInterval(frameLeft, 10);
function frameRight() {
if (startPosition >= 100) {
clearInterval(intervalRight);
frameLeft();
} else {
startPosition += 0.5;
document.getElementById("moveAnimation").style.left = startPosition + "%";
}
}
function frameLeft() {
if (startPosition <= 0) {
clearInterval(intervalRight);
frameRight();
} else {
startPosition -= 2;
document.getElementById("moveAnimation").style.right = startPosition + "%";
}
}
}
</script>
This is the exercise:
Below this, you have a div that needs to move left to right using JS for the motion. Make it reach the end in 2 seconds, then return in 5s. Repeat that forever.
Have updated your code. Use below
<div id="moveAnimation" class="block"></div>
</div>
<script>
var elem = document.getElementById("moveAnimation");
elem.addEventListener("click", movingImage);
function movingImage() {
var startPosition = 0;
var intervalRight = setInterval(frameRight, 10);
var rightTimer = true;
var leftTimer = false;
var intervalLeft;
function frameRight() {
if(!rightTimer){
rightTimer = true;
intervalRight = setInterval(frameRight,10)
return;
}
if (startPosition >= 100) {
rightTimer = false;
clearInterval(intervalRight);
frameLeft();
} else {
startPosition += 0.5;
document.getElementById("moveAnimation").style.left = startPosition + "%";
}
}
function frameLeft() {
if(!leftTimer){
leftTimer = true;
intervalLeft = setInterval(frameLeft,10)
return;
}
if (startPosition <= 0) {
leftTimer = false;
clearInterval(intervalLeft);
frameRight();
} else {
startPosition -= 2;
document.getElementById("moveAnimation").style.left = startPosition + "%";
}
}
}
</script>
After testing some more i've found the answer with fewer lines of code.
var elem = document.getElementById("moveAnimation");
elem.addEventListener("click", movingImage);
function movingImage() {
var startPosition = 0;
var intervalRight = setInterval(frameRight, 10); //1
function frameRight() {
if (startPosition >= 100) {
clearInterval(intervalRight);
intervalLeft = setInterval(frameLeft, 10);
} else {
startPosition += 0.5;
document.getElementById("moveAnimation").style.left = startPosition + "%";
}
}
function frameLeft() {
if (startPosition <= 0) {
clearInterval(intervalLeft);
intervalRight = setInterval(frameRight, 10);
} else {
startPosition -= 0.2;
document.getElementById("moveAnimation").style.left = startPosition + "%";
}
}
}
</script>
this works how it Should. In the original code I posted the clearInterval was not linked to an actual intervalID
Is it possible to pause a requestAnimationFrame?
When i click on a specific button, the animation has to be paused.
And by click the button another time the animation has to be continued.
public addProgressbar() {
const progressbar = $('.progressbar__value');
const max = this.$progressMax;
const time = (1000 / max) * 5;
let start = null;
this.progress = 0;
const step = timestamp => {
if (start === null) {
start = timestamp;
}
this.progress = timestamp - start;
progressbar[0].style.width = Math.min(this.progress / 50, 2000).toFixed() + '%';
if (this.progress < 5000) {
requestAnimationFrame(step);
}
};
setTimeout(() => {
window.requestAnimationFrame(step);
}, 1000);
}
function animate(elem,style,from,to,time) {
if (!elem) return;
var start = new Date().getTime(),
timer = setInterval(function() {
var step = Math.min(1, (new Date().getTime() - start) / time);
elem.style[style] = (from + step * (to - from))+'px';
if (step == 1) clearInterval(timer);
}, 25);
elem.style[style] = from + 'px';
}
Here is my code. and i need to pause and play in it
Finally i found the answer
function animate(elem,style,to,time,callback)
{
if(!elem) return;
_animating = true;
curAnimElem = elem; /*stores the current Element*/
curStyle = style; /*stores the current style*/
curTo = to; /*stores the current to 'px'*/
curCallback = callback; /*stores the current callbak function*/
if(style === 'left'){ from = elem.offsetLeft; }
else if(style === 'top'){ from = elem.offsetTop; }
var start = new Date().getTime(),
animTimer = setInterval(function()
{
if(!pauseV)
{
pauseTime = Math.round(time - (new Date().getTime()-start));
var step = Math.min(1,(new Date().getTime()-start)/time);
elem.style[style] = (from+step*(to-from))+'px';
if( step == 1 ){ _animating = false; clearInterval(animTimer); if(callback){callback(); callback = null;} }
}
else{clearInterval(animTimer);}
},25);
elem.style[style] = from + 'px';
}
the above code is to animate the elements(left or top only). to PAUSE and PLAY, include the below code in pause/play event function.
function pauseFun()
{
if(pauseV)
{
pauseV = false;
if(_animating){ animate(curAnimElem,curStyle,curTo,pauseTime,curCallback); }
}
else if(!pauseV)
{pauseV = true;}
}
Its works for me......
Thanks.
Use clearInterval(timer) to pause the animation and then timer = setInterval(...) again to resume it. You would need to break the setInterval callback out into its own named function (inside the body of the first function) to make resuming easier.
try this:
var doAnimation=true;
var timer=0;
var start=undefined;
function animate(elem,style,from,to,time)
{
if(!elem && doAnimation) return;
if(start==undefined)start = new Date().getTime();
timer = setInterval(function(){
var step = Math.min(1,(new Date().getTime()-start)/time);
elem.style[style] = (from+step*(to-from))+'px';
if( step == 1){
doAnimation=false;
clearInterval(timer);
elem.style[style] = from+'px';
start=undefined;
}},25);
}
function fun(){
doAnimation=!doAnimation;
if(doAnimation){play();}
else{pause();}
}
function play(){
animate( document.getElementById('box'),'left',0 , 200, 7000);
}
function pause(){
clearInterval(timer);
}
$(document).ready(function(){
play();
});
Check out the fiddle here:
http://jsfiddle.net/sunnykumar08/V9MHN/1/
To create a ticking movement and not a sliding one of a number on a canvas i want to move the number up in 0,2 secondes and wait 0,8 seconds. The codes works good for a sliding movement but to implement the ticking i get lost.
jsfiddle
var ittt = 0;
var add = null;
function MinuteTimer() {
add = setInterval(function () {
totime();
if (ittt % (40 * 60) == 0) {
ittt = 0;
}
}, 5);
};
function stoptimer() {
clearInterval(add);
};
function totime() {
drawcanvasbackground();
drawnumberscanvas(ittt);
ittt += 1;
if (ittt % 40 == 0 && ittt > 0) {
clearInterval(add);
setTimeout(MinuteTimer(), 800);
};
};
Problem: In a slide show the fade function below keeps calling the fadein/out functions, please JsFiddle and run for about ten seconds to see problem. Does not work in IE, don't let the jsfiddle run too long it'll probably crash your browser!
JsFiddle: http://jsfiddle.net/HdYmH/
Details (for those interested) : Hi, sorry for posting a question with such a large code chunk. I'm still learning javascript and was trying to figure out how to make a slideshow. I know there are a lot of js slideshows out there but I wanted to figure it out as a learning experience. So be warned there are parts of this code that are very bad. The problem is probably related to the slideshow's changeSlide() method.
I used firebug to find out which method was being called the most apparently after a few seconds fadeOut will be called 20k+ times :|
// Generic fade function that fades in or out
function fade(pElem, pStartOpac, pEndOpac, fps, sec) {
if ((typeof (pElem) !== "string") || (typeof (pStartOpac) !== "number")
|| (typeof (pEndOpac) !== "number") || (typeof (fps) !== "number")
|| (typeof (sec) !== "number")) {
console.log("Parameters incorrect format has to be (string) Element Id, (double) Starting Opacity, (double) End Opacity, (integer) frames per second, (integer) seconds to run");
return;
}
// The CSS opacity property only works from 1 to 0
if (pStartOpac < 0) {
pStartOpace = 0;
}
if (pStartOpac > 1) {
pStartOpac = 1;
}
if (pEndOpac < 0) {
pEndOpac = 0;
}
if (pEndOpac > 1) {
pEndOpac = 1;
}
// Stop the fps from going over 60 or under 1 (The eye will barely notice
// improvements above 60fps and fractional fps are not supported)
if (fps > 60) {
fps = 60;
}
if (fps < 1) {
fps = 1;
}
var totalFrames = (fps * sec);
var opacityChangePerSecond = (Math.abs(pStartOpac - pEndOpac) / sec);
var opacityChangePerFrame = (opacityChangePerSecond / fps);
var timeOutInterval = 1000 * (1 / fps);
// console.log("totalFrames: "+totalFrames);
// console.log("Opacity change per second: " + opacityChangePerSecond);
// console.log("Opacity change per frame: " + opacityChangePerFrame);
// console.log("Time out interval: " + timeOutInterval + " milliseconds");
var opacity = pStartOpac;
var timeoutVar;
var elemId = document.getElementById(pElem);
elemId.style.opacity = opacity;
if (pStartOpac < pEndOpac) {
fadeIn();
return;
} else {
fadeOut();
return;
}
function fadeIn() {
opacity = opacity + opacityChangePerFrame;
if (opacity > pEndOpac) {
clearTimeout(timeoutVar);
return;
}
elemId.style.opacity = opacity;
timeoutVar = setTimeout(fadeIn, timeOutInterval);
return;
}
function fadeOut() {
if (opacity < pEndOpac) {
clearTimeout(timeoutVar);
return;
}
opacity = opacity - opacityChangePerFrame;
if (opacity < 0) {
opacity = 0;
}
elemId.style.opacity = opacity;
timeoutVar = setTimeout(fadeOut, timeOutInterval);
return;
}
}
Got the problem: when opacity gets <0 you set it to 0, and then do: if (opacity < pEndOpac). pEndOpac is 0 so, 0<0 evaluates to false and timeout is never cleared. The solution is to do if (opacity <= pEndOpac):
function fadeIn() {
opacity = opacity + opacityChangePerFrame;
if (opacity >= pEndOpac) {
clearTimeout(timeoutVar);
return;
}
elemId.style.opacity = opacity;
timeoutVar = setTimeout(fadeIn, timeOutInterval);
return;
}
function fadeOut() {
if (opacity <= pEndOpac) {
clearTimeout(timeoutVar);
return;
}
opacity = opacity - opacityChangePerFrame;
if (opacity < 0) {
opacity = 0;
}
elemId.style.opacity = opacity;
timeoutVar = setTimeout(fadeOut, timeOutInterval);
return;
}