kadina
kadina

Reputation: 5384

movement of image is not smooth while image is moving slow

I was trying to move an image to the left continuously (with a time delay) but I am unable to get the smoothness effect. I am getting jerky effect. I am using requestAnimationFrame inside the setTimeout as below.

<!DOCTYPE html>
<html>
    <head>
        <title>Moving Screen Saver</title>
        <style>
            html, body {
              background-image: url("https://s14.postimg.cc/jei3ov2nl/moon_bg.png");
                background-repeat: no-repeat;
            background-size: cover;
                position: relative;
                height: 100%;
                width: 100%;
            }

            #poster {
                background-image: url("https://s14.postimg.cc/582ctpzj5/gladiator.png");
                position: absolute;
                background-position:right 20px bottom 20px;
                background-repeat: no-repeat;
                width: 100%;
                height: 100%;
                z-index: 99999;
                background-color: transparent;
            }
        </style>
    </head>
    <body>
        <div id="poster"></div>

        <script>
            var poster = document.getElementById('poster');
            var animate;

            function moveLeft()
            {
                poster.style.left = poster.style.left || 0;
                poster.style.left = parseInt(poster.style.left) - 10 + 'px';
                setTimeout(function() {
                        requestAnimationFrame(moveLeft);
                        }, 50);
                //requestAnimationFrame(moveLeft);
            }

            moveLeft();
        </script>
    </body>
</html>

If I change the interval to 10 in setTimeout() (or if I just use requestAnimationFrame instead of timeout), the movement is smooth but it is too fast and user can't see properly. Can anyone please let me know is there anyway to achieve the smooth effect with slow moving?

Below is the jsfiddle link

https://jsfiddle.net/un45c6s3/7/

Upvotes: 0

Views: 1027

Answers (2)

Jaromanda X
Jaromanda X

Reputation: 1

As pointed out in a comment, this simple effect is better done using CSS transition, however, for the sake of learning:

Using setTimeout will always make things jerky, as setTimeout timing is not exactly consistent

The code below uses only requestAnmationFrame, and the speed is adjustable (specified in pixels per second)

Note: parseInt changed to parseFloat - because you can have fractional positioning of elements

var poster = document.getElementById('poster');
var animate;
var previousMs = 0;
var speed = 100; // pixels per second
function moveLeft(ms) {
  if (previousMs !== 0) {
    var delta = ms - previousMs;
    // lets say we want to move 100px per second
    // we have d milliseconds, so speed*delta/1000;
    poster.style.left = poster.style.left || 0;
    poster.style.left = parseFloat(poster.style.left) - (speed * delta / 1000) + 'px';
  }
  previousMs = ms;
  requestAnimationFrame(moveLeft);
}
requestAnimationFrame(moveLeft);
html,
body {
  background-image: url("https://s14.postimg.cc/jei3ov2nl/moon_bg.png");
  background-repeat: no-repeat;
  background-size: cover;
  position: relative;
  height: 100%;
  width: 100%;
}

#poster {
  background-image: url("https://s14.postimg.cc/582ctpzj5/gladiator.png");
  position: absolute;
  background-position: right 20px bottom 20px;
  background-repeat: no-repeat;
  width: 100%;
  height: 100%;
  z-index: 99999;
  background-color: transparent;
}
<div id="poster"></div>

Now, you mention in the comment you want to do something when the animation is done

You can do so using CSS transitions and events

window.addEventListener('load', () => {
  var poster = document.getElementById('poster');
  poster.classList.add('move');
  var done = function() {
	  poster.classList.toggle('move');
  };
  poster.addEventListener('transitionend', done);
});
html,
body {
    background-image: url("https://s14.postimg.cc/jei3ov2nl/moon_bg.png");
    background-repeat: no-repeat;
    background-size: cover;
    position: relative;
    height: 100%;
    width: 100%;
    padding:0;
    margin:0;
}

#poster {
    background-image: url("https://s14.postimg.cc/582ctpzj5/gladiator.png");
    position: absolute;
    background-position: right 20px bottom 20px;
    background-repeat: no-repeat;
    width: 100%;
    height: 100%;
    z-index: 99999;
    background-color: transparent;
    left:0;
    transition:left 5s linear;
}
#poster.move {
    left:-100%;
}
<div id="poster"></div>

Upvotes: 2

Why do it in javascript ? can you use CSS ?

the animations in CSS are amazing and are quite supported by the browsers, try it this way

Click on image for animate.

html, body {
	background-image: url("https://s14.postimg.cc/jei3ov2nl/moon_bg.png");
	background-repeat: no-repeat;
    background-size: cover;
	position: relative;
	height: 100%;
	width: 100%;
			}
			
#poster {
	background-image: url("https://s14.postimg.cc/582ctpzj5/gladiator.png");
	position: absolute;
	background-position:right 20px bottom 20px;
	background-repeat: no-repeat;
	width: 100%;
	height: 100%;
	z-index: 99999;
	background-color: transparent;

        /* transition animation slow */
        transition: right 1000ms ease; 

        /* set init of animation */
        right:0%; 

			}
 .posterToLeft{
        right: 100% !important; 
        /* for example end of animation-transition */
      }
	<div id="poster" onclick='this.className +=" posterToLeft";'></div>

Upvotes: 1

Related Questions