How to create a slider locked to an axis

Hello, I am trying to figure out how to lock the position of a slider to a specific axis.

The slider starts at a point on the edge of a circle and needs to end in the center. The user should be able to move the slider (mouseY) and it should only go straight to the center.

Edit: It’s important to note the circle will rotate with the sliders in place, so the positions of the sliders will change but they should still only go straight towards the center.

The circle can rotate as well, but I already have that set up as well as the outside points staying put as the circle rotates.

I feel like I have the solution and its simple, my brain just isn’t working right now.

Thanks!

1 Like

Hi,

If I understand well your issue, it looks like this right ? :slight_smile:

// The diameter of the circle
int circleSize = 300;

// The diameter of the button
int buttonSize = 50;

// The y location of the button
int buttonY = circleSize / 2;

void setup() {
  size(500, 500);
}

void draw() {
  background(255);

  translate(width/2, height/2);

  // Display the circle
  stroke(0);
  strokeWeight(2);
  fill(100);
  ellipse(0, 0, circleSize, circleSize);

  // Display the line
  stroke(0);
  strokeWeight(5);
  line(0, 0, 0, circleSize/2);
  
  // Display the button
  stroke(0);
  strokeWeight(3);
  fill(255, 0, 0);
  ellipse(0, buttonY, buttonSize, buttonSize);
}

void mouseDragged() {
  if (dist(mouseX, mouseY, width/2, height/2 + buttonY) < buttonSize/2) {
    buttonY += (mouseY - pmouseY);
    buttonY = constrain(buttonY, 0, circleSize / 2);
  }
}

Capture d’écran de 2020-06-09 11-24-01

Note : This is a simplified example, you should use classes in your real code

2 Likes

Yes, except now the whole thing needs to work after rotating the circle (45 degrees for example). My apologies, that was not clear.

Oh ok a thought about that but I wasn’t sure :slight_smile:

This is my take on this, it took a little bit to figure out the trigonometry behind it but it works fine. This solution involve classes, if you don’t know about them it’s a key feature in the Java laguage to structure your project :

The idea is that by computing the difference between the previous mouse position (pmouseX and pmouseY) and the current mouse position, you get the movement of the mouse.

Now it works when the slider doesn’t have an angle but when there’s one, basically we compute the difference in X and Y, multiply them respectively by the cosine and the sine of the rotation of the button and then add them.

It looks like this :

float diff = cos(rotation) * (mouseX - pmouseX) + sin(rotation) * (mouseY - pmouseY);

Now if rotation = 0 then cos(0) = 1 and sin(0) = 0 so only the X location of the mouse is contributing to the movement of the slider. If the angle increase to 45° then it’s going to be half of the difference on each coordinates of the mouse and so on…

This is the full code :

CircleButton button;

void setup() {
  size(500, 500);

  button = new CircleButton(width/2, height/2, 300, 50);
}

void draw() {
  background(255);

  button.display();
  
  // Rotate the button
  button.rotation += 0.01;
}

// For each of the mouse actions, we delegate it to the button instance
void mousePressed() {
  button.mousePressed();
}

void mouseReleased() {
  button.mouseReleased();
}

void mouseDragged() {
  button.mouseDragged();
}

class Slider {
  // The diameter of the slider
  int diameter;
  
  // The position of the slider between 0 and 1
  float position = 1;

  Slider(int diameter) {
    this.diameter = diameter;
  }

  void display() {
    stroke(0);
    strokeWeight(3);
    fill(255, 0, 0);
    ellipse(0, 0, diameter, diameter);
  }
  
  // Add an offset to the position of the slider
  // Constrain it between [0, 1]
  void addOffset(float offset) {
    this.position = constrain(position + offset, 0, 1);
  }
}

class CircleButton {
  // The position of the button
  int x, y;
  
  // The diamater of the button
  int diameter;
  
  // It's rotation in radians
  float rotation = 0;
  
  // The slider
  Slider slider;

  int mouseClickedX, mouseClickedY;
  boolean clicked = false;

  CircleButton(int x, int y, int diameter, int sliderDiameter) {
    this.x = x;
    this.y = y;
    this.diameter = diameter;

    // Create the slider
    this.slider = new Slider(sliderDiameter);
  }

  void display() {
    pushMatrix();
    
    // Translate to its location and rotate
    translate(x, y);
    rotate(rotation);

    // Display the circle
    stroke(0);
    strokeWeight(2);
    fill(100);
    ellipse(0, 0, diameter, diameter);

    // Display the line
    stroke(#239BBF);
    strokeWeight(20);
    line(0, 0, diameter/2 * slider.position, 0);
    
    stroke(20);
    line(diameter/2 * slider.position, 0, diameter/2, 0);

    // Display the slider
    // Translate to it's position
    translate(slider.position * diameter / 2, 0);
    slider.display();

    popMatrix();
    
    // Text for the slider position
    stroke(0);
    text("Slider position : " + slider.position, 50, 20);
    text("Mouse clicked : " + clicked, 50, 40);
    text("Rotation : " + floor(degrees(rotation)) + " °", 50, 60);
  }
  
  // Return the X slider coordinate
  float getSliderX() {
    return x + cos(rotation) * slider.position * diameter/2;
  }
  
  // Return the Y slider coordinate
  float getSliderY() {
    return y + sin(rotation) * slider.position * diameter/2;
  }

  void mousePressed() {
    // If the mouse is inside the slider
    if (dist(mouseX, mouseY, getSliderX(), getSliderY()) < slider.diameter/2) {
      // Set clicked to true
      clicked = true;
    }
  }

  void mouseReleased() {
    // Set clicked to false
    clicked = false;
  }

  void mouseDragged() {
    // If we already clicked
    if (clicked) {
      // Compute the offset based on the previous mouse position
      float diff = cos(rotation) * (mouseX - pmouseX) + sin(rotation) * (mouseY - pmouseY);
      
      // Add the offset to the position of the slider
      slider.addOffset(map(diff, 0, diameter/2, 0, 1));
    }
  }
}

slide

Feel free to ask questions if you need! :wink:

5 Likes

Thank you thank you thank you!!!

1 Like