HTML5 Canvas Slider Control Without Using Range Input

In this article I will describe the implementation and use of Slider Control without use of HTML5 Range Input.

Introduction

In this article I will describe the implementation and use of Slider Control without use of HTML5 Range Input.

Slider Bar in HTML5

A slider is also known as a Track Bar. A Slider Control is a useful control for user input having a fixed range. It allows us to render a slider whose position represents a value in a range you specify. Generally a Slider Control is used for user input.

 A slider consists of a knob and a bar for the knob to slide on. The leftmost side of the bar represents a minimum value, the rightmost represents the maximum value. The user can slide the bar and choose the value they like.

It is different from a Scrollbar. A Scrollbar is used to adjust a value without changing the format of the display or the other information on the screen.

With the range input element, we can create sliding controls but here in this article we will create a sliding bar without range input.

What does a Slider Control look like

The figure given below represents a Slider Control

 sliderimg.jpg

Browser Support

The Slider Control is supported only by Google Chrome and Safari. It is not supported by Internet Explorer and Mozilla Firefox.

Procedure for building the Slider Control

Step 1

We first define a HTML5 canvas element. The height and width attributes set the canvas size.

<canvas id="can" height="200" width="300"></canvas>

Step 2

In the following step we add the styles. In that we use a class selector to specify a style for a group of elements. Since the class selector is most often used on several elements, this allows you to set a particular style for many HTML elements with the same class.

In this example we have used a class selector (.slider,.bar,.knob) inside the style tag to style a set of elements to act as a slider.

<style>

   canvas {

       position: absolute;

       top: 10px;

       left: 10px;

       background-color: green;

       border-radius: 25px;

       border: 3px solid black;

   }

 

   .slider {

       position: absolute;

       top: 110px;

       left: 85px;

       width: 150px;

       height: 50px;

    }

 

    .bar {

        position: relative;

        top: 30px;

        width: 150px;

        height: 2px;

        background-color: black;

     }

 

     .knob {

         position: relative;

         left: 0;

         border: 1px solid black;

         background-color: blue;

         width: 50px;

         height: 50px;

         border-radius: 20px;

     }

</style>

Step 3

In order to interact with this canvas through JavaScript, we will need to first get the element by Id and then create a context.

<script type="text/javascript">

    var can = document.getElementById('can');

    var ctx = can.getContext("2d");

</script>

Step 4

In the script tag we declare some variables and methods.

We first define the textInit() method for describing the text properties (such as text alignment, font, textbaseline,etc.); see:

function textInit()

{

   ctx.fillStyle = "blue";

   ctx.font = "20pt Ariel";

   ctx.textAlign = "center";

   ctx.textBaseline = "bottom";

 

}

Step 5

In the following step we will create a "showVal()" function. In this function the value on the slider goes from 0 to the slider width minus the knob width:

function showVal()

{

   var sliderVal = knob.offsetLeft;

   ctx.save();

   ctx.clearRect(0, 0, can.width, can.height);

   var scale = .25 + sliderVal / 200;

   ctx.scale(scale, scale);

   ctx.drawImage(image, 0, 0);

   ctx.restore();

   ctx.fillText(sliderVal, can.width / 2, can.height - 5);

   setTimeout(showVal, 25);

}

 

Step 6

In the "init()" method we first get the element by Id for the slider, knob and canvas separately and then create a context. At last in this method we will call both the textInit() method and showVal() method. We assign a zero value to the mouseIsDown variable.

function init()

{

    slider = document.getElementById("slider");

    knob = document.getElementById("knob");

    image = document.getElementById("image");

    can = document.getElementById("can");

    ctx = can.getContext("2d");

    mouseIsDown = 0;

    knobMid = knob.offsetWidth / 2;

    margin = can.offsetLeft - 1;

    textInit();

    showVal();

}

Step 7

In the following step we create the "mouseXY(ev)" method. In this method we check whether the "if(mouseIsDown)" condition is true or not.

function mouseXY(ev)

{

  if (mouseIsDown)

   {

     if (!ev)

         var ev = event;

     var mouseX = ev.pageX - slider.offsetLeft;

         if (mouseX >= 0 && mouseX <= slider.offsetWidth)

          {

             setKnob(mouseX);

          }

     }

}

 

Step 8

 

In the following step we create the "touchXY(ev)" method. In this method we begin touch event handlers with the "preventDefault()" method to allow the finger to drag the slider instead of scrolling the page.

function touchXY(ev)

{

   if (!ev)

      var ev = event;

   // slide, don't scroll

   ev.preventDefault();

   var touchX = ev.touches[0].pageX - slider.offsetLeft;

   if (touchX >= 0 && touchX <= slider.offsetWidth)

    {

      setKnob(touchX);

    }

}

 

Step 9

 

In the following step we will create a "setKnob()" method. The knob value of the mouse or touch event's pageX property, minus the slider's offsetLeft property. The knob should be positioned half its width to the left of the knob value, so the mouse or finger drags the center of the knob. The knob value should be clamped at 0 and the bar width minus the knob width.

 

function setKnob(x)

{

   var knobX = x - knobMid;

   knobX = Math.max(knobX, 0);

   knobX = Math.min(knobX, slider.offsetWidth - knob.offsetWidth);

   knob.style.left = knobX;

}

 

Step 10

 

In the following step we create the "mouseup()" method on the body element and track the mouse button state.

 

function mouseUp()

{

   mouseIsDown = 0;

 

}

 

Step 11

In the following step we create "mouseDown()" method. In this method we assign 1 to the mouseIsDown varibale and then call the mouseXY() method.

function mouseDown()

{

   mouseIsDown = 1;

   mouseXY();

}

 

Step 12 

 

In the following step the body tag uses three nested div elements. The outermost div element is the slider and is positioned absolutely. The two inner div elements are the bar and the knob, and are positioned relatively within the slider. The bar div is styled into a horizontal line and the knob div is styled into a circle using CSS.

<body onload="init()" onmouseup="mouseUp()">

    <canvas id="can" height="200" width="300"></canvas>

    <div class="slider" id="slider"

        onmousedown="mouseDown()" onmousemove="mouseXY()"

        ontouchstart="touchXY()" ontouchmove="touchXY()">

        <div class="bar"></div>

        <div id="knob" class="knob"></div>

        <img id="image" style="display: none" />

    </div>

</body>

Example

<!DOCTYPE html>

 

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">

<head>

    <meta charset="utf-8" />

    <title>Slider in HTML5</title>

    <meta name="view" content="width=400" />

    <style>

        canvas {

            position: absolute;

            top: 10px;

            left: 10px;

            background-color: green;

            border-radius: 25px;

            border: 3px solid black;

        }

 

        .slider {

            position: absolute;

            top: 110px;

            left: 85px;

            width: 150px;

            height: 50px;

        }

 

        .bar {

            position: relative;

            top: 30px;

            width: 150px;

            height: 2px;

            background-color: black;

        }

 

        .knob {

            position: relative;

            left: 0;

            border: 1px solid black;

            background-color: blue;

            width: 50px;

            height: 50px;

            border-radius: 20px;

        }

    </style>

    <script type="text/javascript">

        var can, ctx, image, slider,

            knob, mouseIsDown, knobMid;

 

        function init() {

            slider = document.getElementById("slider");

            knob = document.getElementById("knob");

            can = document.getElementById("can");

            ctx = can.getContext("2d");

            mouseIsDown = 0;

            knobMid = knob.offsetWidth / 2;

            margin = can.offsetLeft - 1;

            textInit();

            showVal();

        }

 

        function textInit() {

            ctx.fillStyle = "blue";

            ctx.font = "20pt Ariel";

            ctx.textAlign = "center";

            ctx.textBaseline = "bottom";

        }

 

        function showVal() {

            var sliderVal = knob.offsetLeft;

            ctx.save();

            ctx.clearRect(0, 0, can.width, can.height);

            var scale = .25 + sliderVal / 200;

            ctx.scale(scale, scale);

            ctx.drawImage(image, 0, 0);

            ctx.restore();

            ctx.fillText(sliderVal, can.width / 2, can.height - 5);

            setTimeout(showVal, 25);

        }

 

        function mouseDown() {

            mouseIsDown = 1;

            mouseXY();

        }


        function mouseUp() {

            mouseIsDown = 0;

        }

 

        function mouseXY(ev) {

            if (mouseIsDown) {

                if (!ev)

                    var ev = event;

                var mouseX = ev.pageX - slider.offsetLeft;

                if (mouseX >= 0 && mouseX <= slider.offsetWidth) {

                    setKnob(mouseX);

                }

            }

        }

 

        function touchXY(ev) {

            if (!ev)

                var ev = event;

            // slide, don't scroll

            ev.preventDefault();

            var touchX = ev.touches[0].pageX - slider.offsetLeft;

            if (touchX >= 0 && touchX <= slider.offsetWidth) {

                setKnob(touchX);

            }

        }

 

        function setKnob(x) {

            var knobX = x - knobMid;

            knobX = Math.max(knobX, 0);

            knobX = Math.min(knobX, slider.offsetWidth - knob.offsetWidth);

            knob.style.left = knobX;

        }

    </script>

</head>

<body onload="init()" onmouseup="mouseUp()">

    <canvas id="can" height="200" width="300"></canvas>

    <div class="slider" id="slider"

        onmousedown="mouseDown()" onmousemove="mouseXY()"

        ontouchstart="touchXY()" ontouchmove="touchXY()">

        <div class="bar"></div>

        <div id="knob" class="knob"></div>

        <img id="image" style="display: none" />

    </div>

</body>

</html>

 

Output

Figure 1

When the Knob is at beginning(zero)

slider1.jpg

Figure 2

When we move the knob with the mouse

slider2.jpg

Figure 3

When the knob is positioned at the end

slider3.jpg