A Radial Menu, also known as a Pie Menu, is a circular contextual menu. The interface is a pretty cool and intuitive one and is now easy to implement on your site!
Radial menu's are powerful primarily because the location of the menu items can be easily memorized by novice users, as well as experienced ones. The interface effectively engages users in a way in which they are capable of placing directional and gestural associations with particular actions; think muscle memory.
This plugin was created to harness the power of the radial menu and yet provide enough flexibility to
the developer to express their creativity in its application. The radmenu plugin essentially builds items
around the circumference of a circle. This is done by using
unit circle trigonometry, where a simple calculation
x1 = x0 + (Math.cos(angle) * Radius),
y1 = y0 + (Math.sin(angle) * Radius)
allows us to grab the x and y coordinates that the elements are to be positioned; since the elements
are absolutely positioned. When building the items in the list, each item is given its particular 'portion'
of the pie - ( (element # / # elements) * 2 * Math.PI ) - which leads
to an equal distribution of the elements.
The plugin provides the following API - Showing and Hiding the menu on any specified event, Rotating the menu clockwise & counter-clockwise, shuffle the menu items randomly (fireworks-esque effect), specify a custom event to occur after an animation (i.e. clockwise/anticlockwise/shuffling) and performing some function when selecting a radmenu item.
The options that can be set are - The class of the markup containing your list items (listClass), the class of the markup that represents your active element (itemClass), an active class when a radmenu item has been selected (activeItemClass), the radius you want to build the radial menu around, a particular angular offset if you have a desired angle at which you would like the items to be visible, specific center axis (x,y) coordinates of the circle that the radmenu items are built around, and the speed of the animations.
If you have any comments, suggestions, or need/want help implementing this plugin - please feel free to email me @ ntikku@gmail.com or tweet me @ntikku . Also, if you do end up implementing this plugin, I would greatly appreciate it if you would send a link over - I'd love to see it in action!
Thanks,
Nirvana Tikku
<html> <body> <div id='radial_container'> <ul class='list'> <li class='item'> <div class='my_class'> 0 </div> </li> <li class='item'> <div class='my_class'> 1 </div> </li> <li class='item'> <div class='my_class'> 2 </div> </li> <li class='item'> <div class='my_class'> 3 </div> </li> <li class='item'> <div class='my_class'> 4 </div> </li> <li class='item'> <div class='my_class'> 5 </div> </li> <li class='item'> <div class='my_class'> 6 </div> </li> <li class='item'> <div class='my_class'> 7 </div> </li> <li class='item'> <div class='my_class'> 8 </div> </li> <li class='item'> <div class='my_class'> 9 </div> </li> </ul> </div> </body> </html>
<script type='text/javascript' src='{your_path_to}/jQuery.radmenu.js'></script>
#radial_container {
position:relative;
left:425px;
top: 75px;
width:100px;
height:100px;
text-align:center;
}
.radial_div_item {
background-color:none;
height:30px;
padding:10px;
color:#234;
-moz-border-radius:10px;
-webkit-border-radius:10px;
cursor:pointer;
}
.radial_div_item.active {
background-color:#511; color:white;
padding: 10px;
-moz-border-radius:40px;
z-index:100;
}
.my_class {
font-size:1.5em;
color:#abc;
background-color:#def;
-moz-border-radius:30px;
width:30px;
height:30px;
-webkit-border-radius:30px;
}
jQuery("#radial_container").radmenu({ listClass: 'list', // the list class to look within for items itemClass: 'item', // the items - NOTE: the HTML inside the item is copied into the menu item radius: 100, // radius in pixels animSpeed:400, // animation speed in millis centerX: 30, // the center x axis offset centerY: 100, // the center y axis offset selectEvent: "click", // the select event (click) onSelect: function($selected){ // show what is returned alert("you clicked on .. " + $selected.index()); }, angleOffset: 0 // in degrees });
<a href="#" onClick='jQuery("#radial_container").radmenu("show")'> Show Menu </a> <a href="#" onClick='jQuery("#radial_container").radmenu("hide")'> Hide Menu </a> <a href="#" onClick='jQuery("#radial_container").radmenu("next")'> Rotate Menu Clockwise </a> <a href="#" onClick='jQuery("#radial_container").radmenu("prev")'> Rotate Menu Anti-Clockwise </a> <a href="#" onClick='jQuery("#radial_container").radmenu("shuffle")'> Shuffle Items in the Menu </a>
var defaults = { listClass: "list", // the class of the list containing the menu items itemClass: "item", // the classes on the menu items activeItemClass: "active", // the class put on the active element in the menu selectEvent: null, // click, mouseenter, custom etc, a event to be bound onSelect: function($selected){}, // when selections occur, $selected is passed to this method radius: 10, // in pixels the radius of the menu initialScale: 1, // initial scale factor of radius angleOffset: 0, // in degrees the angle that the elements are offset at centerX: 0, // the center x coordinate centerY: 0, // the center y coordinate animSpeed: 500, // the speed of animation when next/prev/shuffle animEasing: "swing", // the type of easing used when animating the raditems scaleAnimSpeed: 0, // the speed of animation when scaling scaleAnimEasing: "swing", // the type of easing used when animating scaleAnimOpts: {}, // the animation options you desire to apply to scaling afterAnimation: function($m){}, // after the animation occurs, passing the 'menu' package onShow: function($items){$items.show();}, // on show, the items are passed in - default show() is called onHide: function($items){$items.hide();} // on hide, the items are passed in - default hide() is called, onNext: function($items){return true;}, // condition for the next event onPrev: function($items){return true;} // condition for the prev event, onScaleItem: function($item, scaleFactor, coords){} // when scaling item, the item, the factor being applied and the new position coordinates are passed through, rotate: false, // if you want the items to be rotated getRotation: function(degrees, index, numItems){return degrees;} // specify a specific angle for the rotation items };
$.radmenu = {
container: {
clz: "radial_div", // the radmenu container class
itemClz: "radial_div_item", // the class to be applied to each menu item
html: "<div></div>", // the container html (without the class)
css: { "position": "relative" } // the css applied to the radial div container
}
};
jQuery("#radial_menu").radmenu("show");
jQuery("#radial_menu").radmenu("show", function(items){ items.fadeIn(1000); });
jQuery("#radial_menu").radmenu("hide");
jQuery("#radial_menu").radmenu("next");
jQuery("#radial_menu").radmenu("prev");
jQuery("#radial_menu").radmenu("shuffle");
jQuery("#radial_menu").radmenu("select", 0);or
jQuery("#radial_menu").radmenu(0);
jQuery("#radial_menu").radmenu("scale", 1.5);
jQuery("#radial_menu").radmenu("items");
jQuery("#radial_menu").radmenu("opts");
jQuery("#radial_menu").radmenu("destroy");
.radial_container {
position:relative;
left:125px;
top: 150px;
width:100px;
height:100px;
text-align:center;
}
.radial_div_item {
background-color:none;
width:75%;
height:30px;
padding:10px;
color:#234;
}
.radial_div_item.active {
background-color:#511;
color:white;
padding: 10px;
-webkit-border-radius:40px;
-moz-border-radius:40px;
}
jQuery(".radial_container").radmenu({
radius: 140,
animSpeed:400,
centerX: 30,
centerY: -20,
selectEvent: "click",
rotate: true,
onSelect: function($selected){
alert($selected.html());
},
angleOffset: 0
});
.cog_1 {
position:relative;
left:250px;
top:50px;
}
.cog_2 {
position:relative;
left:100px;
top:150px;
}
.radial_div_item {
background-color:none;
width:75%;
height:30px;
padding:10px;
color:#234;
}
jQuery(".cog_1").radmenu({
radius: 50,
animSpeed:600,
centerX: 70,
centerY: 20,
rotate: true,
angleOffset: 0
});
jQuery(".cog_2").radmenu({
radius: 100,
animSpeed:400,
centerX: 30,
centerY: -20,
rotate: true,
angleOffset: 0
});
function startClock(){
jQuery(".clock_seconds_hand, .clock_minute_hand, .clock_hour_hand")
.radmenu("show");
CLOCK = setInterval(function(){
jQuery(".clock_seconds_hand")
.radmenu(new Date().getSeconds());
jQuery(".clock_minute_hand")
.radmenu(new Date().getMinutes());
jQuery(".clock_hour_hand")
.radmenu((new Date().getHours())%12);
}, 1000);
};
function stopClock(){ window.clearInterval(CLOCK); };
.clock_seconds_hand,
.clock_minute_hand,
.clock_hour_hand{
position:relative;
left:125px;
top: 150px;
width:100px;
height:100px;
text-align:center;
}
.clock_seconds_hand .radial_div_item.active,
.clock_minute_hand .radial_div_item.active,
.clock_hour_hand .radial_div_item.active {
background-color:transparent;
font-weight:bold;
}
jQuery(".clock_seconds_hand").radmenu({
radius: 170,
animSpeed:400,
centerX: 40,
centerY: 60,
selectEvent: "click",
angleOffset: -90
});
jQuery(".clock_minute_hand").radmenu({
radius: 120,
animSpeed:400,
centerX: 40,
centerY: -40,
selectEvent: "click",
angleOffset: -90
});
jQuery(".clock_hour_hand").radmenu({
radius: 60,
animSpeed: 800,
centerX: 40,
centerY: -130,
selectEvent: "click",
angleOffset: -90
});
#nested_container {
position:relative;
left:170px;
top: 25px;
width:100px;
height:100px;
text-align:center;
}
.list .item .sublist,
.sublist {
display:none;
}
.my_class_main,
.my_class_sub {
font-size:1.5em;
color:#123;
background-color:#567;
-moz-border-radius:30px;
width:30px;
height:30px;
-webkit-border-radius:30px;
}
.my_class_sub {
background-color:#def;
color:#123;
}
#nested_container .radial_div_item {
background-color:none;
height:30px;
padding:10px;
color:#234;
-moz-border-radius:10px;
-webkit-border-radius:10px;
cursor:pointer;
}
#nested_container .radial_div_item.active {
background-color:#511; color:white;
padding: 10px;
-moz-border-radius:40px;
z-index:100;
}
jQuery(document).ready(function(){
jQuery("#nested_container").radmenu({
listClass: 'list', // the list class to look within for items
itemClass: 'item', // the items
radius: 100, // radius in pixels
animSpeed:400, // animation speed in millis
centerX: 30, // the center x axis offset
centerY: 100, // the center y axis offset
selectEvent: "click", // the select event (click)
onSelect: nestedSelection,
angleOffset: 0 // in degrees
});
});
var jlastSelected;
var build = true;
// the onSelect method for the main radmenu
function nestedSelection(jselected){
// make sure that there are elements
if(jselected.length){
// only do this if a parent menu item has been selected
if(jlastSelected) {
if(jlastSelected.is(":visible")){ // if theres an active radmenu item, i.e it's visible
// check to see if its the parent of the nested menu item
if(jlastSelected.parents(".radial_div").length){
jlastSelected.radmenu("hide"); // hide the radmenu
build = false; // we don't want to build a new radmenu
}
}else { // this is a new selection
jlastSelected = null;
build = true; // we want to build the sublist if avail.
}
}
if(build){
// build the sublist radmenu and show it
jselected.radmenu(selectedRadmenuOptions).radmenu("show");
// add some effects for the menu selections
jselected.siblings().fadeTo("slow", 0.32);
jselected.fadeTo("slow", 1);
// store the last item so for nested elements
jlastSelected = jselected;
}else{
// toggle : show the parent radmenu (i.e. 'reset' the main radmenu)
jselected.parents(".radial_div").radmenu("show");
}
}
};
// sublist menu options
var selectedRadmenuOptions = {
listClass: "sublist",
itemClass: "subitem",
select: "click",
rotate:true,
onSelect: function(jselected){
//update the box in the top right corner with the selected item's HTML
jQuery("#nested_selection").html(jselected.html());
jselected.siblings().fadeTo("slow", 0.32);
jselected.fadeTo("slow", 1);
},
radius: 50,
centerX: -10,
centerY: -40,
angleOffset: 0
};
YouTube QuickPlay - By Nirvana Tikku
TubeLoop - By Nirvana Tikku
193King - By Derek McKee
Quality Schools International - By Josh Olson
v1.0.0 - May 14, 2011
v0.9.8 - Sept 11, 2010
v0.9.7 - Sept 9, 2010
v0.9.6 - Sept 5, 2010
v0.9.5 - July 28, 2010
v0.9.4 - July 27, 2010
v0.9.3 - July 15, 2010
v0.9.2 - June 29, 2010
v0.9.1 - June 26, 2010
v0.9 - June 20, 2010
jQuery 1.4.2+
Yes, please! Check out the project @
http://github.com/nirvanatikku/jQuery-Radmenu-Plugin
Nirvana Tikku, Tikku.com © 2010-2013