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 ?

``````// 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);
}
}
``````

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

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]
this.position = constrain(position + offset, 0, 1);
}
}

class CircleButton {
// The position of the button
int x, y;

// The diamater of the button
int diameter;

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 (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