Sliders
Introduction
Sliders are basic elements that allow two types of internal elements:
handles and marks. A slider is initialized by a Surface
which is used as the track. As such, the slider will automatically
inherit the surface's orientation constraints.
Below is an example of a common horizontal slider:
Code:
var surface = new Surface('horizontal');
var slider = new Slider(surface);
slider.trackClassName = 'shaded';
slider.createHandle(Slider.basicHandle('arrow', 'down')).place(0.5);
As you can see, we first create a horizontal surface line (0 height) and designate it as the track when creating the slider. This automatically constrains the slider handle movement to be horizontal.
Vertical Sliders
Similar to horizontal sliders, vertical sliders arise when the slider track is based on a vertical surface.
var surface = new Surface('vertical');
var slider = new Slider(surface);
slider.trackClassName = 'shaded';
slider.createHandle(Slider.basicHandle('arrow', 'left')).place(0.5);
In this case the slider's handle(s) will be constrained to move vertically.
2D Sliders
Finally, sliders can also be 2-dimensional when the track surface is not constrained (a basic area surface).
var surface = new Surface();
var slider = new Slider(surface);
slider.createHandle(Slider.basicHandle('circle', 'uniform')).place(0.5);
Multiple Handles and Handle Styling
Sliders can have multiple handles that are independently controlled.
Below is an example of a common horizontal slider with two separate handles (one pointing up and one pointing down):
Code:
var handle1 = slider.createHandle(Slider.basicHandle('arrow', 'down')).place(0.5);
var handle2 = slider.createHandle(Slider.basicHandle('arrow', 'up')).place(0.8);
Actually, handles are just standard div
s that are
mounted on a point surface, so you can customize them however you
like:
var customHandle = _('div', { className: 'my-handle'}, [
_('div', { className: 'handle-tick' }),
_('div', { className: 'caption-text'}, [_('', 'Hey! This can be anything')])
]);
slider.createHandle(customHandle).place(0.6);
Programmable Constraints
Constraints can be implemented on handles to create all kinds of
functionality. This is done by overloading the _place
method of a handle:
var discreteTicks = [0.1, 0.3, 0.4, 0.6, 0.9, 1.0];
var handle = slider.createHandle(Slider.basicHandle('arrow', 'down')).place(0.5);
var oldPlace = handle._place;
handle._place = function (x, y) {
var newX = discreteTicks.reduce(function (acc, cur) {
return (acc == null || Math.abs(x - cur) < Math.abs(x - acc) ) ?
cur : acc;
}, null);
oldPlace.apply(this, [newX, y]);
}
This is a very old-school way of doing method inheritance since our
examples are based on ES5. However, there's nothing stopping you from
extending the base SliderHandle
class if you opt for a
more modern language variant (e.g. TypeScript).
Programmable constraints are a very rich set of tools for controlling sliders. For example, with multiple slider handles, one can write constraints that modify handle behavior relative to the other handles!
The example above is a 2D area-slider with 2 handles. The outer handle is constrained to move within a circle while the inner handle is constrained by the outer handle. Neither of these constraints are built into the slider primitive and yet they can be easily implemented as a programmable constraint! We will leave the implementation details as an exercise to the reader (hint: look at the source!).
Reading handle Value
Values can be read from a handle through its .value()
method. Depending on the slider type, it will return a single number
or an object containing .x
and .y
for the
corresponding horizontal and vertical values:
handle.addEventListener('move', function () {
$('#slider-7-value').innerText = Math.round(this.value() * 1000) / 1000;
});
Remember that the resolution of the value depends on how much area is available to the slider: longer tracks will give you higher resolution for the value.
Static marks and Track Styling
You may have noticed that in examples above, we have set the property
.trackClassName
on a slider. This is a primitive example
of track styling. By default, the track is a div
that
is assumed to span the entire width and height of the slider's backing
Surface
and is where handles and marks are placed.
You are able to do some basic styling to it, though be aware that
setting certain styles (such as width/height) will break a slider's
functionality.
Here is what a slider looks like without track styling. Notice that you won't see any track!
Remember that the resolution of the value depends on how much area is available to the slider: longer tracks will give you higher resolution for the value.