A slider controller is a user-interface element that we are probably all familiar with. How can we create our own custom slider controller? What is the structure, function, behavior of a slider control?
Structure:
Typically we imagine some horizontal rectangle, with an interactive identifier that show the current position of the slider indicator.
Function:
A one dimensional slider is used to determine a value within a given range of values.
Behavior:
When we press down on the slider, we expect the indicator to move to our mouse position if we are currently positioned over the bar. This is similar to button behavior, the button and slider only change values when they are directly under the mouse and there is some mouse movement.
Map:
Our slider will use the processing map() function because it's core functionality is to provide users with the ability to select a value within a range. The map function allows us to provide a visual range and an interactive indicator for the user to modify. In code, we create the mapping from the slider tool geometry: w, h, position, to determine the intended variation in the controlled value, such as hue or length.
Simple Linear Slider
The code below creates a slider that controls the length of a rectangle. It uses the map function. When determining the slider rectangle's range of values, this is determined by the pixel width of the rectangle: w. In order to determine the values we use to determine the slider's current position and current mapping output value, we need to also consider the x-offset of the slider. In other words, if the slider's left-side is positioned along the left side of the canvas, then x offset is 0. This would mean that if the indicator position: sliderX had a value of 20, and if the width of the slider was 40, we'd know that the slider indicator was at the middle of the range. However, if sliderX had a value of 20, but the x coordinate of the slider rectangle was also 20, we'd know that the slider indicator would be at it's minimum value in the range. Since we want flexibility to position the slider anywhere on the canvas, we need to consider the x offset of the slider when determining the slider's value. So the possible values for the slider Indicator will fall in the range of: ( min: x, max: x+w ), and we'll use these ranges in the map function as the slider representation's min, max value.
Slider, Base-Class
How can we define a Slider base class that allows us to create a slider of any size, at any position, that allows selection of values within any range? The map( ) function will allow us to define a generalized Slider base class.
//Class slider //creates a horizontal slider//uses map function to match displayed slider rectangle and //indicatror rectangles with the min, max values provided as input parametersclassSlider {float x, y;float w, h;float min, max;float sliderX;float sliderVal;String label;Slider( float x,float y,float w,float h,float min,float max,String label) {this.x= x;this.y= y;this.w= w;this.h= h;this.min= min;this.max= max;this.label= label; sliderX = x + (w/2); sliderVal =map( sliderX, x, x+w, min, max); }//display split into 2 methods, the background layer displayes voiddisplay() {backgroundLayer();fill(300);rect( x, y, w, h); //slider rectangle - this is changed in child classes fill(360); //inidcator rectanglerect( sliderX-2, y-3,4, h +6);text( int(sliderVal), sliderX +2, y-4); //display the sliderValue }//display background rectangle that has text display //for min, max, labelvoidbackgroundLayer() {pushStyle();fill( 100); rect( x-10, y-20, w+20, h+40); ////outer background rectanglefill( 360); //fill for the text// Create text for min, max, label - displayed under slider rectangletextSize( 12);textAlign(LEFT);text( int(min), x, y+h+15);textAlign(RIGHT);text( int( max), x+w-10, y+h+15);textAlign(CENTER);textSize(14);text( label, x+(w/2), y+h +15);popStyle(); }voidsetSliderVal( float sliderVal) {this.sliderVal= sliderVal;this.sliderX=map( sliderVal, min, max, x, x+w); }//test mouse coordinates to determine if within the slider rectangle//if not changed, return false//set sliderX to current mouseX positionbooleancheckPressed(int mx,int my) {boolean isChanged =false;if ( mx >= x && mx <= x+w && my> y && my< y +h) { //test for >= so endpoints are included isChanged =true; sliderX = mx; sliderVal =map( sliderX, x, x+w, min, max); }return isChanged; }} // end class Slider
Main Tab Code:
In the code below, we use a slider instance to control the scale of an ellipse
Slider slider1;float hue; //modified by the slidervoidsetup(){size( 700,700);colorMode( HSB,360,100,100); slider1 =newSlider( 200,200,200,30,0,360,"Hue"); hue =slider1.sliderVal; //initialize hue using slider to set the initial value}voiddraw(){background( 0);if( mousePressed){boolean isChanged =slider1.checkPressed( mouseX, mouseY);if(isChanged){ hue =slider1.sliderVal; //update hue using updated sliderVal } }slider1.display();fill( hue,100,100); //hue modified by slider1rect( 20,20,50,50); //rectangle hue modified by slider1 }
Can you make a slider to control Hue? Can we use the Slider base class to create a HueSlider class, how do we create a ROYGBIV Gradient Rectangle? Below is the HueSlider class. How would we create a Saturation and Brightness slider?
HueSlider, Child-class
classHueSliderextendsSlider {HueSlider( int x,int y,int w,int h,float min,float max ) { super( x, y, w, h, min, max,"Hue" ); ////calling base class constructor }voiddisplay() { super.backgroundLayer();for (int i=0; i < w; i ++) { //what going on here?float hueVal =map( i,0, w, min, max);stroke(hueVal,100,100);line(i+x, y, i + x, y + h); }fill(sliderVal,100,100);stroke(0);rect(sliderX, y-4,5, h+8); } // end of display} // end of class HueSlider
To create Saturation and Brightness sliders, we need to consider that their display may be dependent on the Hue slider. So, in the main tab of our project, When we check the HueSlider, and before we display the Bright or Sat Sliders, we can use the value of the HueSlider to set their hue attribute.
//in main tab:
void CheckSliders(){
}
//SAT SLIDER
classSatSliderextendsSlider{SatSlider(int x,int y,int w,int h,float min,float max){ super( x, y, w, h, min, max); }voiddisplay(){ super.backgroundLayer();for( int i=0; i < w ; i++){float satVal =map( i,0,w, min, max); stroke( hue, satVal,100); //calculate satVal for each lineline( x+i, y, x+i, y+h); }///indicator rectanglestroke(0); //reset stroke to defaultfill(hue , sliderVal,100); //use sliderVal to set the sat strokeWeight(2);rect( sliderX-3, y-2,6, h+4);strokeWeight(1); }} // end of class
Main Tab Code
Here's how we check the sliders and use the Hue Slider to set the hue value for the SatSlider before we display the SatSlider. The sizeSlider is a base-class type slider. Notice that the reference variable data type for all sliders is of the base-class type.
Slider sizeSlider,hueSlider, satSlider;voidsetup(){size( 600,600);colorMode(HSB,360,100,100);// Slider( float x, float y, float w, float h, float min, float max, String label ){ sizeSlider =newSlider( 20,40,200,30,0,200,"Size"); hueSlider =newHueSlider( 20,140,200,30,0,360); satSlider =newSatSlider( 20,230,200,30,0,100);} //end of setupvoiddraw(){background(0);if(mousePressed){sizeSlider.checkPressed(mouseX,mouseY);hueSlider.checkPressed(mouseX,mouseY);satSlider.checkPressed(mouseX,mouseY); }sizeSlider.display();hueSlider.display();satSlider.hue=hueSlider.sliderVal; //dependency between hue and sat slidersatSlider.display();float hue =hueSlider.sliderVal;float size =sizeSlider.sliderVal;float sat =satSlider.sliderVal;fill( hue, sat,100); //use the sliderVal to change the hue of the ellipseellipse( 400,400, size,size);} //end of draw