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].
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!
The plugin takes a number of options as a parameter object – snap, value and turn:
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.
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.
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 & 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 > |
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!
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); |
- 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.
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 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.
0 comments:
Post a Comment