Time based image "gallery"

Hi,

I have this code where I put several images (100) and load them, i've managed to load them in my html page. And as expected they all show after each other. How could I make the appear one by one over time. So that every 10 second I get a new image on the same position. All images are the same size. So the centering should not be a problem.

my sketch.js has this for now

let faces = [];
//var canvas;

function preload(){
  for (let i = 0; i < 3; i++) {
    faces[i] = createImg('images/' + i + '.jpg');
  }
}

function setup() {
  createCanvas(800, 900);
  //canvas = createCanvas(window.innerWidth, window.innerHeight);

  // put setup code here
}

function draw() {

  image(faces, 0, 0);
  // put drawing code here
}
/*
window.onresize = function(){
  var w = window.innerWidth;
  var h = window.innerHeight;
  cansvas.size(w,h);

}
*/

It should be like an automated slideshow. 

Answers

  • edited December 2017
    • Have a global variable to represent array's current index. Let's call it idx: let idx = 0;.
    • Make a global constant to represent 10 seconds in milliseconds: const INTER = 10 * 1000;.
    • In setup(), invoke setInterval() passing a lambda callback which increases idx, but constraining it within array's length via the modulo (remainder) operator; plus INTER as its 2nd argument:
      setInterval(() => idx = (idx + 1) % faces.length, INTER);
    • And finally in draw(), use that idx for image(): image(faces[idx], 0, 0);
    1. http://ProcessingJS.org/reference/modulo/
    2. https://Developer.Mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval
    3. https://Developer.Mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
  • Hi, I've adjusted the code with you addition.

        let faces = [];
        let idx = 0;
    
        const INTER = 10 * 1000;
    
        function preload(){
          for (let i = 0; i < 4; i++) {
            faces[i] = createImg('images/' + i + '.png');
          }
        }
    
        function setup() {
            createCanvas(800, 900);
            setInterval(() => idx = (idx + 1) % faces.length, INTER);
        }
    
        function draw() {
          image(faces[idx], 0, 0);
        }
    

    But it still give me the pictures below each other, also it has lost the restraint of the image size. Could you check if there is anything not done right in my part of the code? Because my guess it can only be wrong in what I put together before.

    I left all the other stuff out because I just first want to make this to work before I go to the next step.

    Note: I'm working on a npm local server as suggested by p5js pages.

  • edited December 2017

    @GoToLoop UPDATE!

    It does work! But it first shows me the pictures I have below each other, the last picture is the altering one! And that's working nice! Does this have anything to do with the preload function?

    my firefox console gives me

    ReferenceError: loadImg is not defined
    [Learn More]
    sketch.js:8:5
    preload
    http://localhost:8080/p5/sketch/sketch.js:8:5
    p5/this._start<
    http://localhost:8080/p5/p5.js:44807:7
    <anonymous> self-hosted:951:17 p5
    http://localhost:8080/p5/p5.js:45103:7
    _globalInit
    http://localhost:8080/p5/p5.js:46862:7
    
  • edited December 2017 Answer ✓
    • Oops! I hadn't realized your sketch had more problems. :-SS
    • I was just focusing on the array's indices+ setInterval(). :-\"
    • Most obvious bug is the missing background() as the 1st thing to do within draw(): #-o
      https://p5js.org/reference/#/p5/background
    • 2nd 1 is loadImage() should be preferred over createImg() for common cases: ^#(^
      https://p5js.org/reference/#/p5/loadImage
    • Also, for making easier for others to help ya out, host your sketches at: *-:)
      https://OpenProcessing.org/sketch/create
    • Then post its link here for others to try your sketch out. O:-)
    • You can even upload resource files, like images for example, there as well. \m/
  • Hi I indeed needed to use the loadImage() :) and not createImg() /:) or loadImg() #-o I marked you answer as answered! :) ^:)^ ^:)^ ^:)^ ^:)^

    I posted the next step in my project with the new code on openprocessing without the faker.js file (it's paid..). The problem is that it doesn't change the whole word, but each letter after each other. The former sketch is in it for people that are interested in the future.

    let faces = [];
    let idx = 0;
    let fakeidx = 0;
    
    var canvas;
    var consolediv;
    var randomName = faker.name.findName(); // Caitlyn Kerluke
    var randomEmail = faker.internet.email(); // Rusty@arne.info
    var randomCard = faker.helpers.createCard(); // random contact card containing many properties
    
    const INTER = 1.5 * 1000;
    
    function preload(){
      for (let i = 0; i < 4; i++) {
        faces[i] = loadImage('images/' + i + '.png');
      }
    }
    
    function setup() {
        canvas = createCanvas(window.innerWidth, window.innerHeight);
        setInterval(() => idx = (idx + 1) % faces.length, INTER);
        setInterval(() => fakeidx = (fakeidx + 1) % randomName.length, INTER);
        consolediv = createDiv(randomName);
    
    }
    
    function draw() {
      background(0);
      image(faces[idx], window.innerWidth/3, 200, 0, 0);
      text(randomName[fakeidx], 400, 400);
    
      fill(255,255,255);
    
    }
    

    Or should I make a new question for this?

  • The problem is that it doesn't change the whole word, but each letter after each other.

    Ru sure randomName is indeed an array? Seems more likely it is a string! :-?

  • Jep, I put the faker.name.findName() in a array as

    var randomName = [faker.name.findName()]; // Caitlyn Kerluke
    
      for (let n = 0; n < 2000; n++) {
          randomName = text(randomName[fakeidx], 400, 400);
        }
    
        setInterval(() => fakeidx = (fakeidx + 1) % randomName.length, INTER);
    

    I need to look up some more about putting objects in array's. Also no clue what to set the length to because it should be endless...

  • edited December 2017
    • Hard to help out when using some inaccessible paid library, w/ unknown API. :@)
    • Well, just gonna try once more w/ a buncha educated guesses. >:)
    • Seems like that every time you invoke any of those faker methods, you'd get some random data properties, right?
    • Like made up names, e-mails, contact cards, etc.
    • If that's the case, you should create some class Fake to store those properties as 1 object:
      https://Developer.Mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes
    • Then, after using the operator new over that class, push() the created instance to an array:
    1. https://Developer.Mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push
    2. https://Developer.Mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new
    • Let's name that array as fakes[] then: const fakes = []; B-)
    • Now some "fake" code to give you an idea how to. I'll define a function getNewFakeId() too: >-)

    const fakes = [];
    
    function draw() {
      fakes.push(getNewFakeId(faker));
    }
    
    function getNewFakeId({name, internet, helpers}) {
      return new Fake(name.findName(), internet.email(), helpers.createCard());
    }
    
    class Fake {
      constructor(name, email, card) {
        this.name = name, this.email = email, this.card = card;
      }
    }
    
  • edited December 2017

    Since class Fake got data only but no methods, an ordinary object can replace that easily: :\">

    const fakes = [];
    
    function draw() {
      fakes.push(getNewFakeId(faker));
    }
    
    function getNewFakeId({name, internet, helpers}) {
      return {
        name:  name.findName(),
        email: internet.email(),
        card:  helpers.createCard()
      };
    }
    
Sign In or Register to comment.