Home » , , , , , , , , » Free Shiny Knob Control with jQuery and CSS3

Free Shiny Knob Control with jQuery and CSS3




In this tutorial we will be writing a jQuery plugin for creating a shiny knob control. Aptly named knobKnob, this plugin will use CSS3 transformations and jQuery’s new event handling methods to give visitors of your website a new way of interactively choosing a value from a range.
KnobKnob is also on Github.
Update: Thanks to ranyefet the plugin now works on mobile devices [changes].

The HTML

The HTML markup for the page is rather straightforward. We are only going to need a placeholder element for the control – the rest is going to be dynamically generated by the plugin. Just in case, here is the complete markup of the page:

index.html

01<!DOCTYPE html>
02<html>
03    <head>
04        <meta charset="utf-8" />
05        <title>Shiny Switches with CSS3 &amp; jQuery | Tutorialzine Demo</title>
06 
07        <!-- CSS stylesheets -->
08        <link rel="stylesheet" href="assets/css/styles.css" />
09        <link rel="stylesheet" href="assets/knobKnob/knobKnob.css" />
10 
11        <!--[if lt IE 9]>
12          <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
13        <![endif]-->
14    </head>
15 
16    <body>
17 
18        <section id="main">
19 
20            <div id="bars">
21                <div id="control">
22                    <!-- The knob markup will go here -->
23                </div>
24                                <!-- The colorful dividers will go here -->
25            </div>
26 
27        </section>
28 
29        <!-- JavaScript includes -->
30        <script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
31        <script src="assets/knobKnob/transform.js"></script>
32        <script src="assets/knobKnob/knobKnob.jquery.js"></script>
33        <script src="assets/js/script.js"></script>
34 
35    </body>
36</html>
First we include the latest version of jQuery, transform.js which levels cross-browser support of the CSS3 transform properties we will be using, the knobKnob plugin file and script.js, which pulls everything together.
The #control div is where the plugin markup will be generated. Below we will insert divs that will become the colorful bars around it. They are not part of the KnobKnob plugin, we will be showing them depending on the chosen value in the control. KnobKnob also comes with a stylesheet that determines the looks of the knob. You can see it included in the head section.
Now lets write this plugin!
Shiny Knob Control
Shiny Knob Control

The jQuery Code

You can find the plugin source files in the knobKnob folder. To use it in your project simply unzip it in your website’s assets folder and include the files you find inside. Here is the actual plugin file:

assets/knobKnob/knobKnob.jquery.js

001/**
002 * @name        jQuery KnobKnob plugin
003 * @author      Martin Angelov
004 * @version     1.0
006 * @license     MIT License
007 */
008 
009(function($){
010 
011    $.fn.knobKnob = function(props){
012 
013        var options = $.extend({
014            snap: 0,
015            value: 0,
016            turn: function(){}
017        }, props || {});
018 
019        var tpl = '<div class="knob">\
020                <div class="top"></div>\
021                <div class="base"></div>\
022            </div>';
023 
024        return this.each(function(){
025 
026            var el = $(this);
027            el.append(tpl);
028 
029            var knob = $('.knob',el)
030                knobTop = knob.find('.top'),
031                startDeg = -1,
032                currentDeg = 0,
033                rotation = 0,
034                lastDeg = 0,
035                doc = $(document);
036 
037            if(options.value > 0 && options.value <= 359){
038                rotation = currentDeg = options.value;
039                knobTop.css('transform','rotate('+(currentDeg)+'deg)');
040                options.turn(currentDeg/359);
041            }
042 
043            knob.on('mousedown', function(e){
044 
045                e.preventDefault();
046 
047                var offset = knob.offset();
048                var center = {
049                    y : offset.top + knob.height()/2,
050                    x: offset.left + knob.width()/2
051                };
052 
053                var a, b, deg, tmp,
054                    rad2deg = 180/Math.PI;
055 
056                knob.on('mousemove.rem',function(e){
057 
058                    a = center.y - e.pageY;
059                    b = center.x - e.pageX;
060                    deg = Math.atan2(a,b)*rad2deg;
061 
062                    // we have to make sure that negative
063                    // angles are turned into positive:
064                    if(deg<0){
065                        deg = 360 + deg;
066                    }
067 
068                    // Save the starting position of the drag
069                    if(startDeg == -1){
070                        startDeg = deg;
071                    }
072 
073                    // Calculating the current rotation
074                    tmp = Math.floor((deg-startDeg) + rotation);
075 
076                    // Making sure the current rotation
077                    // stays between 0 and 359
078                    if(tmp < 0){
079                        tmp = 360 + tmp;
080                    }
081                    else if(tmp > 359){
082                        tmp = tmp % 360;
083                    }
084 
085                    // Snapping in the off position:
086                    if(options.snap && tmp < options.snap){
087                        tmp = 0;
088                    }
089 
090                    // This would suggest we are at an end position;
091                    // we need to block further rotation.
092                    if(Math.abs(tmp - lastDeg) > 180){
093                        return false;
094                    }
095 
096                    currentDeg = tmp;
097                    lastDeg = tmp;
098 
099                    knobTop.css('transform','rotate('+(currentDeg)+'deg)');
100                    options.turn(currentDeg/359);
101                });
102 
103                doc.on('mouseup.rem',function(){
104                    knob.off('.rem');
105                    doc.off('.rem');
106 
107                    // Saving the current rotation
108                    rotation = currentDeg;
109 
110                    // Marking the starting degree as invalid
111                    startDeg = -1;
112                });
113 
114            });
115        });
116    };
117 
118})(jQuery);
The plugin takes a number of options as a parameter object – snap, value and turn:
  • snap is a number of degrees that are snapped to zero. You can test this by slowly turning the knob down;
  • value is the initial rotation of the knob (also in degrees);
  • turn is a callback function that is called every time the knob is turned. Its only argument is a ratio (from 0 to 1) of the rotation. We will use this function in a moment to determine how many of the colorful dividers to show.
In the code above you can see that we are using the Math.atan2 function (as we did in the PointPoint plugin) to calculate the angle (in radians) between the mouse pointer and the center of the knob. By keeping track of the angle in the start and end position of the drag, we can determine how much to rotate the knob.
Later we are also using jQuery 1.7′s new methods for manipulating event listeners – on and off.
Now lets see how we can use this plugin.

assets/js/script.js

01$(function(){
02 
03    var colors = [
04        '26e000','2fe300','37e700','45ea00','51ef00',
05        '61f800','6bfb00','77ff02','80ff05','8cff09',
06        '93ff0b','9eff09','a9ff07','c2ff03','d7ff07',
07        'f2ff0a','fff30a','ffdc09','ffce0a','ffc30a',
08        'ffb509','ffa808','ff9908','ff8607','ff7005',
09        'ff5f04','ff4f03','f83a00','ee2b00','e52000'
10    ];
11 
12    var rad2deg = 180/Math.PI;
13    var deg = 0;
14    var bars = $('#bars');
15 
16    for(var i=0;i<colors.length;i++){
17 
18        deg = i*12;
19 
20        // Create the colorbars
21 
22        $('<div class="colorBar">').css({
23            backgroundColor: '#'+colors[i],
24            transform:'rotate('+deg+'deg)',
25            top: -Math.sin(deg/rad2deg)*80+100,
26            left: Math.cos((180 - deg)/rad2deg)*80+100,
27        }).appendTo(bars);
28    }
29 
30    var colorBars = bars.find('.colorBar');
31    var numBars = 0, lastNum = -1;
32 
33    $('#control').knobKnob({
34        snap : 10,
35        value: 154,
36        turn : function(ratio){
37            numBars = Math.round(colorBars.length*ratio);
38 
39            // Update the dom only when the number of active bars
40            // changes, instead of on every move
41 
42            if(numBars == lastNum){
43                return false;
44            }
45            lastNum = numBars;
46 
47            colorBars.removeClass('active').slice(0, numBars).addClass('active');
48        }
49    });
50 
51});
The colorful bars that are displayed around the knob are not part of the plugin. And they shouldn’t be – the plugin only handles the control itself which makes it easier to reuse it.
The code above creates a set of 30 divs with colors gradually going from green to red. These are then rotated by 12 degree increments. Thanks to the turn callback function passed to the plugin, this code can determine how many of the colorful bars to show. You can see the rest of the bar styling in assets/css/styles.css.

We are done!

With this our plugin is complete! You can use it as part of control panels and other administrative pages, everywhere you want to give users the ability to choose from a pool of values. In a followup article, we will use this plugin to enhance the new range form element.
Share this article :

0 comments:

Post a Comment

 
Support : Femin Collection | Habitat Design | Kreatifa Media
Copyright © 2013. Kreatifa Media - All Rights Reserved
Template Created by Habitat Design Published by Kreatifa Media
Proudly powered by Blogger