84891

2 images animated using Javascript

Question:

From doing research and asking for help I have so far built an animation moving from left to right using the code in the JSFiddle below. This loops every 20 seconds.

<a href="http://jsfiddle.net/a9HdW/3/" rel="nofollow">http://jsfiddle.net/a9HdW/3/</a>

However now I need a second image that moves from right to left and for this to automatically trigger straight after the first image has completed its animation. If you could do this that would be amazing.

Thanks In Advance

<canvas id="canvas" width="1600" height="300"></canvas> <script> window.requestAnimFrame = (function(){ window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function( callback ){ window.setTimeout(callback, 1000 / 60); }; })(); var canvas = document.getElementById("canvas"), cx = canvas.getContext("2d"); function Card(x,y){ this.x = x || -300; this.y = y || 0; this.width = 0; this.height = 0; this.img=new Image(); this.init=function(){ // this makes myCard available in the img.onload function // otherwise "this" inside img.onload refers to the img var self=this; this.img.onload = function() { // getting width and height of the image self.width = this.width; self.height = this.height; self.draw(); loop(); } this.img.src = "f15ourbase.png"; } this.draw = function(){ cx.drawImage(this.img, this.x, this.y); } } var myCard = new Card(50,50); myCard.init(); function loop(){ if((myCard.x + myCard.width) < canvas.width){ requestAnimFrame(loop); } else { setTimeout(function() { // resetting card back to old state myCard.x = 50; myCard.y = 50; // call the loop again loop(); }, 20000); } cx.clearRect(0, 0, canvas.width, canvas.height); myCard.x = myCard.x + 15; myCard.draw(); }

Answer1:

This is little bit complicated, however, it boils down to formatting your Card function to understand which direction it is going to. Therefore you will need direction parameter and more complicated draw function which updates your card movement to direction it is supposed to go, like this:

// Updating own position, based on direction if(this.direction === 1) { this.x = this.x + this.stepSize; // we move to right // if I am over canvas at right, I am done animating if(this.x >= canvas.width) { this.finishedAnimation = true; } } else { this.x = this.x - this.stepSize; // we move to left // if I am over canvas at left, I am done animating if(this.x <= -this.width) { this.finishedAnimation = true; } }

Also, because timing is important - you will need to trigger other card movement only after the first one is completed. Like this:

// We won't draw next card before previous is finished if(!cardToRight.finishedAnimation) { cardToRight.draw(); } else { // Card at right is finished, we move the left card now cardToLeft.draw(); }

To summarize my points, I made a code which has code comments to explain it's contents, go it through carefully:

// Animation frame gist window.requestAnimFrame = (function(){ return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function( callback ){ window.setTimeout(callback, 1000 / 60); }; })(); // Variable declarations var canvas = document.getElementById("canvas"), cx = canvas.getContext("2d"), // Handlers for both of the cards cardToRight, cardToLeft; /** * Card declaration * */ var Card = function(x, y, direction) { // how many pixels we move this.stepSize = 5; // x and y position on canvas this.x = x; this.y = y; // Copy values are used when reset is done this.xCopy = this.x; this.yCopy = this.y; // handle to specify if animation finished this.finishedAnimation = false; // 1 means move to right, 0 means move to left this.direction = direction; // Image of the card this.img = undefined; // Image url for this card this.imgSrc = "http://placehold.it/350x150"; // for your image: "f15ourbase.png" // Image width this.width = 0; }; /** * Initialize * */ Card.prototype.init = function(callback) { // self refers to this card var self = this; this.img = new Image(); // onload success callback this.img.onload = function() { // Setting own width self.width = this.width; // triggering callback on successfull load return callback(); }; // onload failure callback this.img.onerror = function() { // Returning error message for the caller of this method return callback("Loading image " + this.imgSrc + " failed!"); }; // Triggering image loading this.img.src = this.imgSrc; }; /** * Draw self * */ Card.prototype.draw = function() { // Updating own position, based on direction if(this.direction === 1) { this.x = this.x + this.stepSize; // we move to right // if I am over canvas at right, I am done animating if(this.x >= canvas.width) { this.finishedAnimation = true; } } else { this.x = this.x - this.stepSize; // we move to left // if I am over canvas at left, I am done animating if(this.x <= -this.width) { this.finishedAnimation = true; } } // cx (context) could be also passed, now it is global cx.drawImage(this.img, this.x, this.y); }; /** * Reset self * */ Card.prototype.reset = function() { // Using our copy values this.x = this.xCopy; this.y = this.yCopy; // handle to specify if animation finished this.finishedAnimation = false; }; /** * Main loop * */ function loop() { // Clear canvas cx.clearRect(0, 0, canvas.width, canvas.height); // We won't draw next card before previous is finished // Alternatively, you could make getter for finishedAnimation if(!cardToRight.finishedAnimation) { cardToRight.draw(); } else { // Card at right is finished, we move the left card now cardToLeft.draw(); } // If cardToLeft not yet animated, we are still pending if(!cardToLeft.finishedAnimation) { // Schedule next loop // "return" makes sure that we are not executing lines below this return requestAnimFrame(loop); } // Animation finished, starting again after 5 seconds setTimeout(function() { // Resetting cards cardToRight.reset(); cardToLeft.reset(); // Start the loop again loop(); }, 5000); // 5000 milliseconds = 5 seconds }; /** * Main program below * */ // Card to right (1 denotes it's direction to right) cardToRight = new Card(50, 50, 1); // Card to left (0 denotes it's direction to left) cardToLeft = new Card(1000, 50, 0); // Initialize cardToRight & cardToLeft // Because using only two cards, we can do a bit nesting here cardToRight.init(function(err) { // If error with image loading if(err) { return alert(err); } // Trying to initialize cardToLeft cardToLeft.init(function(err) { // If error with image loading if(err) { alert(err); } // All ok, lets do the main program loop(); }); });

As a special note: If you wan't your cards appear outside the canvas remember to change values of below accordingly:

// Card to right (1 denotes it's direction to right) cardToRight = new Card(50, 50, 1); // 50 <- x position of right card // Card to left (0 denotes it's direction to left) cardToLeft = new Card(1000, 50, 0); // 1000 <- x position of left card

Finally, here is working <strong><a href="http://jsfiddle.net/a9HdW/9/" rel="nofollow">JsFiddle example</a></strong>

Recommend

  • Mouse cursor doesn't match with canvas
  • Canvas change size of drawings live
  • Extend Line based on slope to the end of canvas/drawing area
  • Android SurfaceView: Show Video after Images
  • JSF reset text field [duplicate]
  • Android: How to restore the state of a stopped chronometer after rotation?
  • Get byte[] from
  • IndexSizeError on drawImage on IE and Edge
  • How do I reset a PHP pointer for a MySQL resource? [duplicate]
  • Source file (.py) not compiling (.pyc not updated)
  • Can I call custom javascript from an R jupyter notebook
  • Cannot style mat-tab without ::ng-deep and !important
  • Pyglet uses too much cpu
  • Encrypting credit card details using AngularJS in Braintree
  • How to select table rows/complete table?
  • Get used tables from sql query [duplicate]
  • Why does it draw lines in the wrong place?
  • How to make R's read_csv2() recognise the text characters properly
  • Implementation of State Monad
  • How to have background script and something similar to a default popup?
  • How do I pass the string value parameter of the selected list item from an auto-populated dropdown l
  • Python urlparse: small issue
  • How to use an array of arrays with array_map(…) in PHP?
  • How to rebase a series of branches?
  • All Classes Conforming to Protocol Inherit Default Implementation
  • Get one-time binding to work for ng-if
  • Ajax jQuery multiple calls at the same time - long wait for answer and not able to cancel
  • Perl system calls when running as another user using sudo
  • Statically linking a C++ library to a C# process using CLI or any other way
  • Adding custom controls to a full screen movie
  • How do you troubleshoot character encoding problems?
  • GridView Sorting works once only
  • SVN: Merging two branches together
  • Load html files in TinyMce
  • Change div Background jquery
  • How does Linux kernel interrupt the application?
  • Django query for large number of relationships
  • Busy indicator not showing up in wpf window [duplicate]
  • Conditional In-Line CSS for IE and Others?
  • Why do underscore prefixed variables exist?