【问题标题】:How I can slow down animation while still refreshing at 60 fps?如何在以 60 fps 刷新的同时减慢动画速度?
【发布时间】:2018-07-28 09:47:41
【问题描述】:

我一直在为动画和间隔/fps 的想法而苦恼。我了解此 sn-p 中代码的工作原理,但我只是不明白如何在减慢动画速度的同时仍将画布保持在 60 fps 刷新率。

$(document).ready(function(){
	startAnimating(60);
});

//Global Variables
var fpsInterval;
var then;
var shift = 0;
var frameWidth = 107;
var frameHeight = 140;
var canvasX = 0;
var canvasY = 0;
var myImage = new Image();
var totalFrames = 8;
var currentFrame = 0;
//Loading image
myImage.src = "https://i.imgur.com/N3shTgD.png";
myImage.addEventListener("load", loadImage, false);
//Function to begin animation with set fps
function startAnimating(fps)
{
	fpsInterval = 1000/fps;
	then = Date.now();
	animate();
}

function animate() {

	var now = Date.now();
	var elapsed = now - then;

	if (elapsed > fpsInterval)
	{
		then = now - (elapsed % fpsInterval);
		var cvs = $("canvas").get(0);
		var ctx = cvs.getContext("2d");

		//clear background
		ctx.clearRect(0, 0, cvs.width, cvs.height);
		//draw each frame and place in middle of canvas
		/*
		drawImage(
		"Image object",
		"X coordinate next sprite in png (Location of sprite?)",
		"Y coorinate next sprite in png",
		"Width of sprite in png (How big is sprite?)",
		"Height of sprite in png"
		"X coordinate on canvas (Where to draw it?)"
		"Y coordinate on canvas"
		"Sprite width to use (How you want it to look?)"
		"Sprite height to use"
		)
		*/
		//(sprite.png,0,0,300,300,0,0,300,300)
		ctx.drawImage(myImage, shift, 0, frameWidth, frameHeight, canvasX, canvasY, frameWidth, frameHeight);
		shift += frameWidth + 1;
	}

	if (currentFrame == totalFrames) {
		shift = 0;
		currentFrame = 0;
	}
	currentFrame++;
	requestAnimationFrame(animate);
}
<html>
	<head>
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
		<!-- What code do we need? -->
		<script src ="exercise_three.js"></script>
	</head>
	<body>
		<canvas width="300" height="300" style="border: solid black 1px">
			Sorry, no canvas support!
		</canvas>
	</body>
</html>

https://jsfiddle.net/r7dd2mt7/2/RequestAnimationFrame()

我将非常感谢一些帮助理解它的工作原理。

【问题讨论】:

    标签: javascript


    【解决方案1】:

    有一个简单的替代方案。您可以通过添加超时来简单地减慢动画速度,而不是更改所有精灵。有效地跳过绘制帧,以便按照您的速度进行绘制,而不是按照浏览器的帧绘制速度进行绘制。

    在示例中,我删除了所有杂项并添加了一个速度变量。以毫秒为单位设置您希望每一步采取的措施(每 1/2 秒 500 步)。注意 setTimeout() 调用。

    只是为了好玩,我也用 setInterval 运行你的动画,因为我很好奇。

    检查这个:

    //Global Variables
    var shift = 0;
    var frameWidth = 107;
    var frameHeight = 140;
    var myImage = new Image();
    var totalFrames = 8;
    var currentFrame = 0;
    var left = document.getElementById('left');
    var leftCtx = left.getContext("2d");
    var right = document.getElementById('right');
    var rightCtx = right.getContext("2d");
    
    // in ms, so 500 == 1 step every 1/2 second
    var pace = 250;
    
    myImage.src = "https://i.imgur.com/N3shTgD.png";
    setInterval(rightStep, pace);
    requestAnimationFrame(leftStep);
    
    function leftStep() {
      leftCtx.clearRect(0, 0, left.width, left.height);
      leftCtx.drawImage(myImage, shift, 0, frameWidth, frameHeight, 0, 0, frameWidth, frameHeight);
      shift += frameWidth + 1;
      if(shift === (frameWidth * 8) + 8) {
      	shift = 0;
      }
      setTimeout(stepLeftAgain, pace);
    }
    
    function stepLeftAgain(){
      requestAnimationFrame(leftStep);
    }
    
    function rightStep() {
      rightCtx.clearRect(0, 0, right.width, right.height);
      rightCtx.drawImage(myImage, shift, 0, frameWidth, frameHeight, 0, 0, frameWidth, frameHeight);
      shift += frameWidth + 1;
      if(shift === (frameWidth * 8) + 8) {
      	shift = 0;
      }
    }
    <html>
      <head>
      </head>
      <body>
        <canvas id="left" width="300" height="300" style="border: solid black 1px"></canvas>
        <canvas id="right" width="300" height="300" style="border: solid black 1px"></canvas>
      </body>
    </html>

    【讨论】:

      【解决方案2】:

      60 FPS 表示每 1000 / 60 毫秒(大约 16.7 毫秒)更改帧。因此,如果您只有 8 帧(如您的示例中),则整个循环将花费 133.3 毫秒。当然也太快了。您可以通过两种方式减慢速度:

      • 增加帧数。以下示例使用 45 帧的精灵。动画看起来更流畅、更慢。

      //Global Variables
      var fpsInterval;
      var then;
      var shift = 0;
      var frameWidth = 397;
      var frameHeight = 300;
      var canvasX = 0;
      var canvasY = 0;
      var myImage = new Image();
      var totalFrames = 45;
      var currentFrame = 0;
      //Loading image
      myImage.onload = function() {
          startAnimating(60);
      };
      myImage.src = "https://i.imgur.com/u6uPigf.png";
      //Function to begin animation with set fps
      function startAnimating(fps) {
      	fpsInterval = 1000/fps;
      	then = Date.now();
      	animate();
      }
      
      function animate() {
        var now = Date.now();
        var elapsed = now - then;
        if (elapsed > fpsInterval) {
          then = now - (elapsed % fpsInterval);
          var cvs = $("canvas").get(0);
          var ctx = cvs.getContext("2d");
          //clear background
          ctx.clearRect(0, 0, cvs.width, cvs.height);
          //draw each frame and place in middle of canvas
          /*
          drawImage(
          "Image object",
          "X coordinate next sprite in png (Location of sprite?)",
          "Y coorinate next sprite in png",
          "Width of sprite in png (How big is sprite?)",
          "Height of sprite in png"
          "X coordinate on canvas (Where to draw it?)"
          "Y coordinate on canvas"
          "Sprite width to use (How you want it to look?)"
          "Sprite height to use"
          )
          */
          ctx.drawImage(myImage, shift, 0, frameWidth, frameHeight, canvasX, canvasY, frameWidth, frameHeight);
          shift += frameWidth + 1;
          currentFrame++;
          if (currentFrame == totalFrames) {
              shift = 0;
              currentFrame = 0;
          }
        }
      	requestAnimationFrame(animate);
      }
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
      <canvas width="300" height="300" style="border: solid black 1px">
        Sorry, no canvas support!
      </canvas>
      • 如果您只想使用给定的 8 帧,那么唯一的方法就是降低 FPS 值。例如,这里是 10 FPS 版本。不是那么顺利,但看起来仍然可以接受。

      //Global Variables
      var fpsInterval;
      var then;
      var shift = 0;
      var frameWidth = 107;
      var frameHeight = 140;
      var canvasX = 0;
      var canvasY = 0;
      var myImage = new Image();
      var totalFrames = 8;
      var currentFrame = 0;
      //Loading image
      myImage.onload = function() {
        startAnimating(10);
      }
      myImage.src = "https://i.imgur.com/N3shTgD.png";
      //Function to begin animation with set fps
      function startAnimating(fps) {
      	fpsInterval = 1000/fps;
      	then = Date.now();
      	animate();
      }
      
      function animate() {
        var now = Date.now();
        var elapsed = now - then;
        if (elapsed > fpsInterval) {
          then = now - (elapsed % fpsInterval);
          var cvs = $("canvas").get(0);
          var ctx = cvs.getContext("2d");
          //clear background
          ctx.clearRect(0, 0, cvs.width, cvs.height);
          //draw each frame and place in middle of canvas
          /*
          drawImage(
          "Image object",
          "X coordinate next sprite in png (Location of sprite?)",
          "Y coorinate next sprite in png",
          "Width of sprite in png (How big is sprite?)",
          "Height of sprite in png"
          "X coordinate on canvas (Where to draw it?)"
          "Y coordinate on canvas"
          "Sprite width to use (How you want it to look?)"
          "Sprite height to use"
          )
          */
          ctx.drawImage(myImage, shift, 0, frameWidth, frameHeight, canvasX, canvasY, frameWidth, frameHeight);
          shift += frameWidth + 1;
          currentFrame++;
          if (currentFrame == totalFrames) {
              shift = 0;
              currentFrame = 0;
          }
        }
      	requestAnimationFrame(animate);
      }
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
      <canvas width="300" height="300" style="border: solid black 1px">
        Sorry, no canvas support!
      </canvas>

      【讨论】:

      • 哇,现在一切都说得通了。非常感谢!
      • @PiotrZadka 我很高兴能提供帮助
      猜你喜欢
      • 2017-02-20
      • 2016-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-01
      • 1970-01-01
      • 2020-11-22
      • 2016-01-18
      相关资源
      最近更新 更多