javascript - 在 Canvas 中循环背景图像动画

标签 javascript html canvas html5-canvas

我是 Canvas 的新手,想在下面的烟雾效果中循环背景图像。在搜索时,我找到了一个示例,说明我们如何在 Canvas 中循环背景图像 Link to looping animation所以我尝试将循环代码与烟雾效果相结合,但没有成功。任何帮助将不胜感激。

     // Create an array to store our particles
     var particles = [];
     // The amount of particles to render
     var particleCount = 60;
     // The maximum velocity in each direction
     var maxVelocity = 2;
     // The target frames per second (how often do we want to update / redraw the scene)
     var targetFPS = 33;
     // Set the dimensions of the canvas as variables so they can be used.
     var canvasWidth = window.innerWidth;
     var canvasHeight = window.innerHeight;
     // borders for particles on top and bottom
     var borderTop = 0.01 * canvasHeight;
     var borderBottom = 0.99 * canvasHeight;
     // Create an image object (only need one instance)
     var imageObj = new Image();

     var looping = false;
     var totalSeconds = 0;
     // Once the image has been downloaded then set the image on all of the particles
     imageObj.onload = function() {
       particles.forEach(function(particle) {
         particle.setImage(imageObj);
       });
     };
     // Once the callback is arranged then set the source of the image
     imageObj.src = "https://image.ibb.co/fdpeJF/Smoke.png";
     // A function to create a particle object.
     function Particle(context) {
       // Set the initial x and y positions
       this.x = 0;
       this.y = 0;
       // Set the initial velocity
       this.xVelocity = 0;
       this.yVelocity = 0;
       // Set the radius
       this.radius = 5;
       // Store the context which will be used to draw the particle
       this.context = context;
       // The function to draw the particle on the canvas.
       this.draw = function() {
         // If an image is set draw it
         if (this.image) {
           this.context.drawImage(this.image, this.x - 128, this.y - 128);
           // If the image is being rendered do not draw the circle so break out of the draw function
           return;
         }
         // Draw the circle as before, with the addition of using the position and the radius from this object.
         this.context.beginPath();
         this.context.arc(this.x, this.y, this.radius, 0, 2 * Math.PI, false);
         this.context.fillStyle = "rgba(0, 255, 255, 1)";
         this.context.fill();
         this.context.closePath();
       };
       // Update the particle.
       this.update = function() {
         // Update the position of the particle with the addition of the velocity.
         this.x += this.xVelocity;
         this.y += this.yVelocity;
         // Check if has crossed the right edge
         if (this.x >= canvasWidth) {
           this.xVelocity = -this.xVelocity;
           this.x = canvasWidth;
         }
         // Check if has crossed the left edge
         else if (this.x <= 0) {
           this.xVelocity = -this.xVelocity;
           this.x = 0;
         }
         // Check if has crossed the bottom edge
         if (this.y >= borderBottom) {
           this.yVelocity = -this.yVelocity;
           this.y = borderBottom;
         }
         // Check if has crossed the top edge
         else if (this.y <= borderTop) {
           this.yVelocity = -this.yVelocity;
           this.y = borderTop;
         }
       };
       // A function to set the position of the particle.
       this.setPosition = function(x, y) {
         this.x = x;
         this.y = y;
       };
       // Function to set the velocity.
       this.setVelocity = function(x, y) {
         this.xVelocity = x;
         this.yVelocity = y;
       };
       this.setImage = function(image) {
         this.image = image;
       };
     }
     // A function to generate a random number between 2 values
     function generateRandom(min, max) {
       return Math.random() * (max - min) + min;
     }
     // The canvas context if it is defined.
     var context;
     // Initialise the scene and set the context if possible
     function init() {
       var canvas = document.getElementById('myCanvas');
       canvas.width = window.innerWidth;
       canvas.height = window.innerHeight;
       if (canvas.getContext) {
         // Set the context variable so it can be re-used
         context = canvas.getContext('2d');
         // Create the particles and set their initial positions and velocities
         for (var i = 0; i < particleCount; ++i) {
           var particle = new Particle(context);
           // Set the position to be inside the canvas bounds
           particle.setPosition(generateRandom(0, canvasWidth), generateRandom(borderTop, borderBottom));
           // Set the initial velocity to be either random and either negative or positive
           particle.setVelocity(generateRandom(-maxVelocity, maxVelocity), generateRandom(-maxVelocity, maxVelocity));
           particles.push(particle);
           context.clearRect(0, 0, canvas.width, canvas.height);	
         }
       } else {
         alert("Please use a modern browser");
       }
     }
     // The function to draw the scene
     function draw() {
       //  background image
       context.globalAlpha = 1;
             context.globalCompositeOperation = 'source-over';
       context.drawImage(backImg, 0, 0, canvasWidth, canvasHeight);
       context.fillStyle = "rgba(255,255,255, .5)";
       context.fillRect(0, 0, canvasWidth, canvasHeight);

       context.globalAlpha = 0.75;
        context.globalCompositeOperation = 'soft-lights';
       // Fog layer
       // Go through all of the particles and draw them.
       particles.forEach(function(particle) {
         particle.draw();
       });

     }
     // Update the scene
     function update() {
       particles.forEach(function(particle) {
         particle.update();
       });
     }
     // Initialize the scene
     init();
     backImg = new Image();
      backImg.src = 'https://image.ibb.co/cTOOdF/e2VZQY.jpg';
       // If the context is set then we can draw the scene (if not then the browser does not support canvas)
       if (context) {
         setInterval(function() {
           // Update the scene befoe drawing
           update();
           // Draw the scene
           draw();
         }, 1000 / targetFPS);
       }
<canvas id="myCanvas" ></canvas>

最佳答案

我只是添加了几行。希望你能发现它们。我评论了我添加的所有内容。

// Create an array to store our particles
var particles = [];
// The amount of particles to render
var particleCount = 60;
// The maximum velocity in each direction
var maxVelocity = 2;
// The target frames per second (how often do we want to update / redraw the scene)
var targetFPS = 33;
// Set the dimensions of the canvas as variables so they can be used.
var canvasWidth = window.innerWidth;
var canvasHeight = window.innerHeight;
// borders for particles on top and bottom
var borderTop = 0.01 * canvasHeight;
var borderBottom = 0.99 * canvasHeight;
// Create an image object (only need one instance)
var imageObj = new Image();
// x position of scrolling image
var imageX = 0;

var looping = false;
var totalSeconds = 0;
// Once the image has been downloaded then set the image on all of the particles
imageObj.onload = function() {
  particles.forEach(function(particle) {
    particle.setImage(imageObj);
  });
};
// Once the callback is arranged then set the source of the image
imageObj.src = "https://image.ibb.co/fdpeJF/Smoke.png";
// A function to create a particle object.
function Particle(context) {
  // Set the initial x and y positions
  this.x = 0;
  this.y = 0;
  // Set the initial velocity
  this.xVelocity = 0;
  this.yVelocity = 0;
  // Set the radius
  this.radius = 5;
  // Store the context which will be used to draw the particle
  this.context = context;
  // The function to draw the particle on the canvas.
  this.draw = function() {
    // If an image is set draw it
    if (this.image) {
      this.context.drawImage(this.image, this.x - 128, this.y - 128);
      // If the image is being rendered do not draw the circle so break out of the draw function
      return;
    }
    // Draw the circle as before, with the addition of using the position and the radius from this object.
    this.context.beginPath();
    this.context.arc(this.x, this.y, this.radius, 0, 2 * Math.PI, false);
    this.context.fillStyle = "rgba(0, 255, 255, 1)";
    this.context.fill();
    this.context.closePath();
  };
  // Update the particle.
  this.update = function() {
    // Update the position of the particle with the addition of the velocity.
    this.x += this.xVelocity;
    this.y += this.yVelocity;
    // Check if has crossed the right edge
    if (this.x >= canvasWidth) {
      this.xVelocity = -this.xVelocity;
      this.x = canvasWidth;
    }
    // Check if has crossed the left edge
    else if (this.x <= 0) {
      this.xVelocity = -this.xVelocity;
      this.x = 0;
    }
    // Check if has crossed the bottom edge
    if (this.y >= borderBottom) {
      this.yVelocity = -this.yVelocity;
      this.y = borderBottom;
    }
    // Check if has crossed the top edge
    else if (this.y <= borderTop) {
      this.yVelocity = -this.yVelocity;
      this.y = borderTop;
    }
  };
  // A function to set the position of the particle.
  this.setPosition = function(x, y) {
    this.x = x;
    this.y = y;
  };
  // Function to set the velocity.
  this.setVelocity = function(x, y) {
    this.xVelocity = x;
    this.yVelocity = y;
  };
  this.setImage = function(image) {
    this.image = image;
  };
}
// A function to generate a random number between 2 values
function generateRandom(min, max) {
  return Math.random() * (max - min) + min;
}
// The canvas context if it is defined.
var context;
// Initialise the scene and set the context if possible
function init() {
  var canvas = document.getElementById('myCanvas');
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;
  if (canvas.getContext) {
    // Set the context variable so it can be re-used
    context = canvas.getContext('2d');
    // Create the particles and set their initial positions and velocities
    for (var i = 0; i < particleCount; ++i) {
      var particle = new Particle(context);
      // Set the position to be inside the canvas bounds
      particle.setPosition(generateRandom(0, canvasWidth), generateRandom(borderTop, borderBottom));
      // Set the initial velocity to be either random and either negative or positive
      particle.setVelocity(generateRandom(-maxVelocity, maxVelocity), generateRandom(-maxVelocity, maxVelocity));
      particles.push(particle);
      context.clearRect(0, 0, canvas.width, canvas.height);  
    }
  } else {
    alert("Please use a modern browser");
  }
}
// The function to draw the scene
function draw() {
  //  background image
  context.globalAlpha = 1;
  context.globalCompositeOperation = 'source-over';
  // draw twice to cover wrap around
  context.drawImage(backImg, imageX, 0, canvasWidth, canvasHeight);
  context.drawImage(backImg, imageX + canvasWidth, 0, canvasWidth, canvasHeight);
  context.fillStyle = "rgba(255,255,255, .5)";
  context.fillRect(0, 0, canvasWidth, canvasHeight);

  context.globalAlpha = 0.75;
   context.globalCompositeOperation = 'soft-light';
  // Fog layer
  // Go through all of the particles and draw them.
  particles.forEach(function(particle) {
    particle.draw();
  });

}
// Update the scene
function update() {
  // incrementally change image position of background to scroll left
  imageX -= maxVelocity;

  if (imageX < -canvasWidth) {
    imageX += canvasWidth;
  }

  particles.forEach(function(particle) {
    particle.update();
  });
}
// Initialize the scene
init();
backImg = new Image();
backImg.src = 'https://image.ibb.co/cTOOdF/e2VZQY.jpg';
// If the context is set then we can draw the scene (if not then the browser does not support canvas)
if (context) {
  setInterval(function() {
    // Update the scene befoe drawing
    update();
    // Draw the scene
    draw();
  }, 1000 / targetFPS);
}
<canvas id="myCanvas"></canvas>

关于javascript - 在 Canvas 中循环背景图像动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44064172/

相关文章:

javascript - 如何确保在 Javascript 中多次调用时所有事件都未附加?

javascript - 解密 RSA 数据时出现 DOMException

html - 创建标题/内容 CSS 网格布局的更简洁方法

html - 如何使用 Bootstrap 排列列/行

javascript - Canvas 和颜色交换

android - Canvas 随机移动

javascript - 在 Winston 日志框架中实现 Promise

php - 无限滚动 MySQL 数据

html - 将多个并排的 div 居中

javascript - 使用 John Resig 的 Processing.js 是否合理?