Animate a Property of an Object with jQuery

After some messing around with jQuery.animate() I figured out how to animate properties of an Object:

      $({x:0}).animate({x:100},{
        duration : 1000, 
        step:function(){
          console.log(this.x);
        }
      });

This might look a little chunky, but it’s actually not bad when put to real use.

Click anywhere on the below canvas:

Here is the code:

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
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title></title>
    <script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
    <script src="easing.js"></script>
    <script>
      $(function(){
 
        var win = $(window);
        var canvas = $("<canvas>").appendTo("body")[0];
        canvas.width = win.width();
        canvas.height = win.height();
        var c = canvas.getContext("2d");
        c.fillStyle = "black";
        c.fillRect(0,0,canvas.width,canvas.height);
 
        function Triangle(x,y,color){
          var t = this;
          t.x = x;
          t.y = y;
          t.color = color;
        }
        Triangle.prototype = {
          rotation : 0, scaleX : 1, scaleY : 1,
          render : function(){
            var t = this;
            c.save();
            c.translate(t.x,t.y);
            c.rotate(t.rotation);
            c.scale(t.scaleX,t.scaleY);
            c.fillStyle = t.color;
            c.beginPath();
            c.moveTo(0,-30);
            c.lineTo(30,30);
            c.lineTo(-30,30);
            c.closePath();
            c.fill();
            c.restore();
          }
        };
 
        $.fx.interval = 30;
 
        var triA = new Triangle(100,100,"red");
        var $triA = $(triA);
 
        var triB = new Triangle(200,100,"blue");
        var $triB = $(triB);
 
        $(document).click(function(){
          $triA.stop().animate({
            x : Math.random() * canvas.width,
            y : Math.random() * canvas.height,
            rotation : Math.random() * 2 * Math.PI,
            scaleX : 0.5 + Math.random(),
            scaleY : 0.5 + Math.random()
          }, 500, "easeOutBack");
 
          $triB.stop().animate({
            x : Math.random() * canvas.width,
            y : Math.random() * canvas.height,
            rotation : Math.random() * 2 * Math.PI,
            scaleX : 0.5 + Math.random(),
            scaleY : 0.5 + Math.random()
          }, 2000, "easeOutElastic");
        });
 
        setInterval(function(){
          c.fillStyle = "rgba(0,0,0,0.2)";
          c.fillRect(0,0,canvas.width,canvas.height);
 
          triA.render();
          triB.render();
 
        },$.fx.interval);
 
      });
    </script>
    <style>
      body,html{
        overflow : hidden;
        margin:0px;
        padding:0px; 
      }
    </style>
  </head>
  <body>
 
  </body>
</html>

Digg

Raphael Pie Chart Part 1

So awhile back I created a pie chart in raphael without the use of the SVG arc command. So, my old pie chart works, but it has lots of vector points – it’s all done with moveTo and lineTo. Rather than use the pie chart example from Raphael, I wanted to see if I could create my own from scratch. I got 80% there but then had to peak at how this (http://raphaeljs.com/growing-pie.html) example works. Here are a few arcs put together:

And here is the source code:

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
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title></title>
    <script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
    <script src="raphael-min.js"></script>
    <script>
      $(function(){
 
        var p = new Raphael(0,0,"100%","100%");
 
        p.path(arc(200,200,150,0,2) +
               arc(200,200,150,2,3) + 
               arc(200,200,150,3,4.5) + 
               arc(200,200,150,4.5,5) + 
               arc(200,200,150,5,Math.PI*2)).attr("stroke", "white");
 
        function arc(x, y, radius, start, end){
          var f = ((end - start) > Math.PI) ? 1 : 0;
 
          var sx = radius * Math.cos(start);
          var sy = radius * Math.sin(start);
          var ex = x + radius * Math.cos(end);
          var ey = y + radius * Math.sin(end);
 
          var path = "M " + x + " " + y + " l " 
              + sx + " " + sy + " A " + radius 
              + " " + radius + " 0 " + f + " 1 " 
              + ex + " " + ey + " z";
          return path;
        }
 
      });
    </script>
    <style>
      body,html{
        background-color : #333;
      }
    </style>
  </head>
  <body>
 
  </body>
</html>

SVG arc commands are pretty confusing. I had a few problems making this. The first was that I used “L” instead of “l”. Turns out “l” is relative positioning. Another problem was the large-arc-flag and the sweep-flag. I’m still not sure I fully grasp these.

Unlike the one in the example from raphaeljs.com I wanted my arc function to use radians. Over the years I’ve just gotten used to working in radians instead of degrees. I also prefer building a large string rather than using a series of arrays to define a path. Here is what the arc segment function looks like from raphaeljs.com:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
r.customAttributes.segment = function(x, y, r, a1, a2) {
  var flag = (a2 - a1) > 180,
      clr = (a2 - a1) / 360;
  a1 = (a1 % 360) * Math.PI / 180;
  a2 = (a2 % 360) * Math.PI / 180;
  return {
    path: [
      ["M", x, y],
      ["l", r * Math.cos(a1), r * Math.sin(a1)],
      ["A", r, r, 0, +flag, 1, x + r * Math.cos(a2), y + r * Math.sin(a2)],
      ["z"]
    ],
    fill: "hsb(" + clr + ", .75, .8)"
  };
};

I formatted this a bit for readability.

Digg

jQuery on() Map

Another nice feature of jQuery on() is that it accepts an object literal for its event type. So you can use one call to on() to set multiple event listeners.

Here is the code:

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
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title></title>
    <script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
    <script>
      $(function(){
        var debug = $("#debug");
 
        $(".box").on({
          click : function(){
            debug.append("click ");
          }, 
          mouseover : function(){
            $(this).css({backgroundColor : "red"});
          }, 
          mouseout : function(){
            $(this).css({backgroundColor : "#7e9fc2"});
          }
        });
 
      });
    </script>
    <style>
      body,html{
        background-color : #333; 
        font-family : Helvetica, sans-serif;
      }
      .box{
        position: relative;
        float : left;
        width : 50px;
        height : 50px;
        margin : 2px;
        padding : 5px;
        background-color : #7e9fc2 ;
        cursor : pointer;
        font-size : 11px;
      }
      #debug{
        position : relative;
        clear : both;
        border : 1px solid gray;
        color : white;
      }
    </style>
  </head>
  <body>
    <div class="box">click me</div>
    <div class="box">click me</div>
    <div class="box">click me</div>
    <div id="debug"></div>
  </body>
</html>

Digg