Mix video with static images added later to canvas

Dear Community,

since many years im a designer and webdev and just came across p5.js - It blows my mind, there are so much things i can imagine :slight_smile:

Please have a look here:
https://editor.p5js.org/slgdev/sketches/gc2_lR6_B

I want to have a mix between videos and static images stacked together.
In my future vision the vid/img will not be there at first draw, because they are added later via different buttons.

A)
In my snippet above you can see the button which adds a 2nd image to the canvas. It works but only for 1 frame (not visible because to fast - uncomment line 17 to see it works).

B)
If you only uncomment line 18 with noLoop() and run the snippet again, press the button, the 2nd image appears on the canvas. But now the video isnt running :-/

Anybody can help me get the problem solved? :slight_smile: Thx in advance.
Cant wait to show you what i have done in the future.

Best
slgdev

Hello and welcome!

The thing is, if you draw stuff outside draw(), it will be erased by next draw frame.
When you press the button the image is displayed, but immediately erased by stuff in draw.

If you comment out the background()call in draw(), you will see the image as expected. But usually you want the call to clear the screen in draw().

There are several approaches possible, but I think you are looking for this one:

Use the button to set a boolean, and move the actual image() call to draw() with the condition to draw or not.

If you intent to have several images, you could instead add them to an array with the button code and display all images of that array in draw.

here a fast fix just to illustrate.

let img1;
let img2;
let vid1;
let button;
let show = false;


function preload() {
  img1 = loadImage("img1.png");  
  img2 = loadImage("img2.png");  
  vid1 = createVideo("vid1.mp4");
}


function setup() {
  createCanvas(500, 500);
  
  //frameRate(1);
  //noLoop();
  
  button = createButton('Add img2 to canvas');
  button.position(20, 30);
  button.mousePressed(pressbtn);
  
  vid1.loop();
  vid1.hide();
}


function draw() {
  background(220);  
  image(vid1, 20, 80, 350, 200);
  image(img1, 250, 0, 250,250);
  if(show)image(img2, 50, 230,200,200);
}


function pressbtn() {
 show = true;
}
1 Like

An example using arrays, click anyware to add images:
(creating the images on the fly)

'use strict'
let imgs = [];
let idi = 0;

function setup() {
  createCanvas(600, 600);
  let t = createNumber(idi);
  imgs.push(t);
}

function draw() {
  background(171);

  let  index = 0;
  let  indey = 0;
  
  for(const im of imgs){
    let w = im.width * index ;
    let h = im.height * indey ;
    image(im, w, h);    
    if ((w + im.width ) < width -  im.width/2){
      index++;
    }else{
      indey++;
      index = 0;
    }
    
  }
  
}

function mousePressed() {
  idi++;
  let t = createNumber(idi);
  imgs.push(t);
}

function createNumber(n) {
  let d = createGraphics(150, 130);
  d.stroke(0);
  d.textFont("Arial");
  d.textSize(110);
  let ns = random(0,35);
  d.background(255, 240- ns, 250 - ns/2);
  let yPos = d.height - 25;
  d.text(n, 0, yPos);
  return d;
}

same thing with regular for loop (no for of)

"use strict";
let imgs = [];
let idi = 0;

function setup() {
  createCanvas(800, 600);
  let t = createNumber(idi);
  imgs.push(t);
}

function draw() {
  background(171);

  let y = 0;
  let x = 0;

  for (let i = 0; i < imgs.length; i++) {
    let h = y * imgs[i].height;
    image(imgs[i], x, h);
    if (x + imgs[i].width < width - imgs[i].width) {
      x += imgs[i].width;
    } else {
      y++;
      x = 0;
    }
  }
}

function mousePressed() {
  idi++;
  let t = createNumber(idi);
  imgs.push(t);
}

function createNumber(n) {
  let g = 11 * textWidth(n);

  let d = createGraphics(g, 130);
  d.stroke(0);
  d.textFont("Arial");
  d.textSize(110);
  let ns = random(0, 35);
  d.background(255, 240 - ns, 250 - ns / 2);
  let yPos = d.height - 25;
  d.text(n, 0, yPos);
  return d;
}