When p5js slider value is released function?

I want to re-draw the canvas when the user is done changing the slider values, how could I do that?

There are two poorly documented (undocumented?) functions on the p5.Element that is returned by createSlider: input() and changed(). Both of these functions take a callback. The callback passed to input() will be called any time the value of the slider changes, as the user is moving the mouse. The callback passed to changed() will be called once the user releases the mouse after having made a change to the slider value. Here’s an example:

let slider;
let liveColor;
let finalColor;
function setup() {
  createCanvas(400, 400);
  finalColor = liveColor = color(128);
  
  slider = createSlider(0, 255, 50);
  slider.input(() => {
    liveColor = color(slider.value())
  });
  
  slider.changed(() => {
    finalColor = color(slider.value());
  });
}

function draw() {
  background(220);
  
  fill(liveColor);
  circle(100, 200, 50);
  
  fill(finalColor);
  circle(300, 200, 50);
}

https://editor.p5js.org/Kumu-Paul/sketches/NNGR8EJmS

1 Like

And, in case it isn’t clear. If you only want to redraw the canvas when this event happens, then you’ll want to call noLoop() in you setup and then call redraw() in the slider changed() callback.

1 Like

Hi @KumuPaul
I am trying to implement this in the following code where I need the objects individually to stay fixed at a certain rotation, and when switching the radio button, reset the position of the slider circle to its respective value. But this only is working for the tube. When I uncomment the lines for the box it doesn’t even reset the tube rotation value anymore. Can you tell me where my logic is flawed?

let box_rX = tube_rX = 0

function setup() {
  createCanvas(400, 300, WEBGL)
  slider = createSlider(0, TWO_PI, 0, 0)
  slider.position(20, 20)
  slider.style("width", "220px")
  radio = createRadio()
  radio.option("tube")
  radio.option("box")
  radio.style("width", "50px")
  radio.position(300, 15)
  radio.option("tube").checked = true
}

function draw() {
  background(220)
  push()
  if (radio.value() == "tube") {
    radio.input(() => {
      slider.value(tube_rX)
    })
    tube_rX = slider.value()
  }
  translate(-100, 0, 0)
  rotateX(tube_rX)
  cylinder(10, 50, 10, 1)
  pop()
  
  push()
  if (radio.value() == "box") {
    //radio.input(() => {
      //slider.value(box_rX)
    //});
    box_rX = slider.value()
  }
  translate(100, 0, 0)
  rotateX(box_rX)
  box(10, 10, 50)
  pop()
}

You will want to avoid registering event handlers (which is what you are doing when you call radio.input(() => ... )) inside of the draw() function. This will cause you to have many many event handlers that all do the same thing. Instead you will want to set up a single event handler in your setup() function that is responsible for updating the slider to reflect the current selected shape:

let box_rX = 0, tube_rX = 0

function setup() {
  createCanvas(400, 300, WEBGL)
  slider = createSlider(0, TWO_PI, 0, 0)
  slider.position(20, 20)
  slider.style("width", "220px")
  radio = createRadio()
  radio.option("tube")
  radio.option("box")
  radio.style("width", "50px")
  radio.position(300, 15)
  radio.option("tube").checked = true
  
  // Whenever the radio button selection changes
  radio.input(() => {
    // update the slider to reflect the selected objects orientation
    if (radio.value() == "tube") {
      slider.value(tube_rX)
    } else {
      slider.value(box_rX)
    }
  });
}

function draw() {
  if (radio.value() == "tube") {
    tube_rX = slider.value()
  } else {
    box_rX = slider.value()
  }
  
  background(220)
  push()
  translate(-100, 0, 0)
  rotateX(tube_rX)
  cylinder(10, 50, 10, 1)
  pop()
  
  push()
  translate(100, 0, 0)
  rotateX(box_rX)
  box(10, 10, 50)
  pop()
}
2 Likes

I get it. This really should be documented in the Reference.
Thanks a lot once more!