Home > CSS, Front End Development, HTML, Javascript > How to Create a 3D Tag Cloud in jQuery

How to Create a 3D Tag Cloud in jQuery

August 10th, 2009


With browsers rendering JavaScript faster than ever before, it’s a great opportunity to get creative with jQuery.  This tutorial will show how to create a scrolling 3D tag cloud…it’s not as difficult as you might think.

 

3D Tag Clouds..Oh My

What exactly will we be building?  It’s somewhat like a carousel, but we’re going to have the take fade off into the distance like the lone ranger at the end of cheesy “B” western flick….very dramatic. 

We’re also going to have our tag cloud interact with the users mouse.  The further the mouse is away from the center, the faster it will rotate.

3d tag cloud

 

Simple HTML

As the sub title suggests the HTML is painfully simple.  Most of the complicated stuff is in the jQuery.  All we’ll need is a list of anchor tags wrapped in a div.  Told you it was simple,  here is the HTML.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <title>jQuery 3D</title>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
   
<div id="list">
    <ul>
        <li><a href="#">ajax</a></li>
        <li><a href="#">css</a></li>
        <li><a href="#">design</a></li>
        <li><a href="#">firefox</a></li>
        <li><a href="#">flash</a></li>
        <li><a href="#">html</a></li>
        <li><a href="#">Devirtuoso</a></li>
        <li><a href="#">jquery</a></li>
        <li><a href="#">PHP</a></li>
        <li><a href="#">SEO</a></li>
        <li><a href="#">usability</a></li>
        <li><a href="#">www</a></li>
        <li><a href="#">web</a></li>
        <li><a href="#">xhtml</a></li>
   
    </ul>
</div> 

</body>
</html>

 

Styling the List

For the most part the CSS is just to make the links pretty.  There are a couple of things that need to happen though.  The anchor links need to have a position: absolute.  This way the jQuery can give it x and y co-ordinates and the links will obey.  Also we need to give a height and width of the div wrapper.  The jQuery reference the dimensions of the wrapper to help layout the links.  It might also be a good idea to give the wrapper a position:relative to keep the links inside the wrapper, this isn’t necessary though.

Here is the CSS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/* Set font and background for body*/  
body{
    font-family: Arial, "MS Trebuchet", sans-serif;
    background-color: #111;
}

/* Styles the div wrapper
the important part is the
width and the height */

#list{
   
    /*Influences layout of list*/
    height:600px;
    width:600px;
   
    background-color: #000;
   
    /* Keeps list inside of wrapper*/
    position:relative;
    margin:0 auto;
    overflow:hidden;
}

/* Reset the list*/
#list ul,
#list li{
    list-style:none;
    margin:0;
    padding:0;
}

/* List requires an absolute position
so jQuery can move the items around
freely */

#list a{
    position:absolute;
    text-decoration: none;
    color:#666;
}
#list a:hover{
    color:#ccc;
}

 

The Fun Part (jQuery)

Now comes the trigonometry….see…your high school teacher was right, you will use this stuff in the real world.  It really isn’t that bad though…3 lines of trigonometry is more than acceptable. I’m not going to go into great detail with the math.  If you want to learn more about the math behind the 3D I recommend reading Kirupa.com tutorial on it. The tutorial is for flash, but you will get the gist of how it works.

Here is the jQuery:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
$(document).ready(function(){
   
//Setup variables
var element = $('#list a'); // all the list elements
var offset = 0;             // angle offset for animation
var stepping = 0.03;        // how fast the list rotates
var list = $('#list');      // the list wrapper
var $list = $(list);

/* Handles mouse movement, the closer to the center
the faster the list will rotate */

$list.mousemove(function(e){
   
    var topOfList = $list.eq(0).offset().top
    var listHeight = $list.height()
   
    // Sets variable that controls the speed of rotation.
    stepping = (e.clientY - topOfList) /  listHeight * 0.2 - 0.1;
   
});


/* Disperse elements evenly around the circle */
for (var i = element.length - 1; i >= 0; i--)
{
    element[i].elemAngle = i * Math.PI * 2 / element.length;
}

// call render function over and over
setInterval(render, 20);


// Handles how and where each element will be rendered.
function render(){
   
    //Steps through each element...
    for (var i = element.length - 1; i >= 0; i--){
       
        // offset adds degrees to where the element
        // is currently on the circle
        var angle = element[i].elemAngle + offset;
       
        // Trig to figure out the size and where the
        // text should go
        x = 120 + Math.sin(angle) * 30;
        y = 45 + Math.cos(angle) * 40;
        size = Math.round(40 - Math.sin(angle) * 40);
       
        // Centers the text, instead of being left aligned.
        var elementCenter = $(element[i]).width() / 2;
       
        // Figure out the x value of the element.
        var leftValue = (($list.width()/2) * x / 100 - elementCenter) + "px"
       
       
        // Apply the values to the text
        $(element[i]).css("fontSize", size + "pt");
        $(element[i]).css("opacity",size/100);
        $(element[i]).css("zIndex" ,size);
        $(element[i]).css("left" ,leftValue);
        $(element[i]).css("top", y + "%");
    }
   
    // Rotate the circle
    offset += stepping;
}
   
   
});

 

Just to step through what we did.  First we setup the mouse event. We figure out how far the mouse is away from the center and assign it to a variable that controls the speed of the scrolling list.

speed

After that we step through each element in our list and give each one a spot on our 3D circle.  A for loop walks through each one, and evenly assigns an angle to each element. (e.g. 1st = 0 degrees, 2nd = 5 degrees, 3rd = 10 degrees…etc)

degrees

After we placed each element on our 3D circle it’s time to animate it.  We use a setInterval to call our render function repeatedly.  The render function steps through each element and figures out where and how it should be displayed.  The trigonometry basically creates a set of numbers that if you plot it on a graph look like a wave. If you apply those numbers to the size of the text, it gives the appearance of going back and forth in space.  If you also apply these numbers to the y, this will give you the appearance that the text is going around in a circle. If you don’t understand the math inside this function not to worry.  I encourage you to play around with the numbers to see how each number effects the outcome.

3d

 

The Finish Line

That’s all there is to it.  Here is the code all together so you can have a look.  Enjoy.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title>jQuery 3D</title>

<style type="text/css" media="screen">
    body{
        font-family: Arial, "MS Trebuchet", sans-serif;
        background-color: #111;
    }
    #list{
        margin:0 auto;
        height:600px;
        width:600px;
        overflow:hidden;
        position:relative;
        background-color: #000;
    }
    #list ul,
    #list li{
        list-style:none;
        margin:0;
        padding:0;
    }
    #list a{
        position:absolute;
        text-decoration: none;
        color:#666;
    }
    #list a:hover{
        color:#ccc;
    }
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js" type="text/javascript" charset="utf-8"></script>

</head>
<body>
   
<div id="list">
    <ul>
        <li><a href="#">ajax</a></li>
        <li><a href="#">css</a></li>
        <li><a href="#">design</a></li>
        <li><a href="#">firefox</a></li>
        <li><a href="#">flash</a></li>
        <li><a href="#">html</a></li>
        <li><a href="#">Devirtuoso</a></li>
        <li><a href="#">jquery</a></li>
        <li><a href="#">PHP</a></li>
        <li><a href="#">SEO</a></li>
        <li><a href="#">usability</a></li>
        <li><a href="#">www</a></li>
        <li><a href="#">web</a></li>
        <li><a href="#">xhtml</a></li>
   
    </ul>
</div>

<script type="text/javascript">


$(document).ready(function(){
   
var element = $('#list a');
var offset = 0;
var stepping = 0.03;
var list = $('#list');
var $list = $(list)

$list.mousemove(function(e){
    var topOfList = $list.eq(0).offset().top
    var listHeight = $list.height()
    stepping = (e.clientY - topOfList) /  listHeight * 0.2 - 0.1;
   
});


for (var i = element.length - 1; i >= 0; i--)
{
    element[i].elemAngle = i * Math.PI * 2 / element.length;
}


setInterval(render, 20);


function render(){
    for (var i = element.length - 1; i >= 0; i--){
       
        var angle = element[i].elemAngle + offset;
       
        x = 120 + Math.sin(angle) * 30;
        y = 45 + Math.cos(angle) * 40;
        size = Math.round(40 - Math.sin(angle) * 40);
       
        var elementCenter = $(element[i]).width() / 2;

        var leftValue = (($list.width()/2) * x / 100 - elementCenter) + "px"

        $(element[i]).css("fontSize", size + "pt");
        $(element[i]).css("opacity",size/100);
        $(element[i]).css("zIndex" ,size);
        $(element[i]).css("left" ,leftValue);
        $(element[i]).css("top", y + "%");
    }
   
    offset += stepping;
}

   
});

</script>

</body>
</html>

 

 

Author:



Top