RaphaelJS Graphics and Visualization on the Web

How to Make Custom Shapes and Curves on HTML5 web pages. Animations Maps, Illustrations, and Other Artifacts.

Chris Wilson

121 Pages

8158 Reads



PDF Format

6.22 MB

Java Script

Download PDF format

  • Chris Wilson   
  • 121 Pages   
  • 03 Mar 2015
  • Page - 1

    www.it-ebooks.info read more..

  • Page - 2

    www.it-ebooks.info read more..

  • Page - 3

    Chris Wilson RaphaelJS Graphics and Visualization on the Web www.it-ebooks.info read more..

  • Page - 4

    RaphaelJS by Chris Wilson Copyright © 2014 Chris W ilson. All rights reserved. Printed in the United States of America. Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472. O’Reilly books may be purchased for educational, business, or sales promotional use. Online editions are also available for most titles ( http://my.safaribooksonline.com). For more read more..

  • Page - 5

    Table of Contents Preface. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . vii 1. Introduction: Why Raphael is Great. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . read more..

  • Page - 6

    Better Dragging 36 Dragging Sets read more..

  • Page - 7

    Pause for Commentary 91 Custom Easing Formulas read more..

  • Page - 8

    www.it-ebooks.info read more..

  • Page - 9

    Preface I once heard programming described as a way to “express your ideas through a com‐ puter.” To me, that morsel of wisdom encapsulates everything that is wonderful and awful about writing code: it gives us the vocabulary to work through our ideas and then lays bare the limits of our ingenuity. If everyone had the same sorts of ideas, we would only need one read more..

  • Page - 10

    The only tool we need for this book, besides a computer, is the Raphael.js library, which is open-source and freely available at RaphaelJS.com under the MIT License. Bringing a few visual ideas to the table won’t hurt, either. By the end of this manual, you’ll be ready to express them in code. Conventions Used in This Book The following typographical conventions are read more..

  • Page - 11

    example code does not require permission. Incorporating a significant amount of ex‐ ample code from this book into your product’s documentation does require permission. We appreciate, but do not require, attribution. An attribution usually includes the title, author, publisher, and ISBN. For example: “ RaphaelJS by Chris Wilson (O’Reilly). Copyright 2014 Chris Wilson, read more..

  • Page - 12

    To comment or ask technical questions about this book, send email to bookques tions@oreilly.com. For more information about our books, courses, conferences, and news, see our website at http://www.oreilly.com. Find us on Facebook: http://facebook.com/oreilly Follow us on Twitter: http://twitter.com/oreillymedia Watch us on YouTube: http://www.youtube.com/oreillymedia Acknowledgments First and foremost, I read more..

  • Page - 13

    CHAPTER 1 Introduction: Why Raphael is Great Raphael is a toolkit for making beautiful things on the Web. With a few lines of code and the help of a small, free JavaScript library, you can turn the browser into a living gallery of interactive artwork and visualization. This book will teach you how to bridge the gulf between the page and your imagination. Let’s dive read more..

  • Page - 14

    See this code live on jsFiddle. If you’re not impressed yet, don’t worry. You’ve actually seen something pretty neat. Let’s go over what we just did: • We took a bare bones HTML page and added a single <div> element with the id container . • We loaded a small JavaScript library named raphael-min.js, which clocks in at 89Kb, hosted on CloudFlare. • We read more..

  • Page - 15

    Inside Every Browser, an Artist I am always a bit puzzled when people talk about data visualization as though it’s a new frontier on the Web, because in some sense everything on the Web is a data visualization. Whether you are hand-coding files for your Harry Potter fan fiction site, dreaming up a video game that runs in the browser, or relaunching a major website read more..

  • Page - 16

    It’s easy Raphael is written entirely in JavaScript, the native language of the Web. JavaScript is a glorious language whose supreme friendliness to inexperienced developers more than compensates for a few design flaws. If you’re new to the world of Web development, Raphael is an excellent place to start because you will immediately be able to see the fruits of your efforts read more..

  • Page - 17

    its name suggests, it specializes in quickly translating raw datasets into visualizations, from Microsoft Excel-style charts and graphs to social network diagrams and sunburst diagrams. If your goal is to make interactive charts and graphs based on large datasets, and if you’re already a confident JavaScript programmer, D3 might be the right place to start. But there’s a reason read more..

  • Page - 18

    on the user’s machine, not on a server somewhere. So you do not need an elaborate development environment, just a way to load your code into a browser. This can be as simple as editing a document with Notepad and loading it in a browser from your desktop, though you ought to do yourself a favor and get a text editor that recognizes code and highlights it in read more..

  • Page - 19

    CHAPTER 2 Shapes In the introduction, we looked at a complete working example of Raphael that drew a red dot on the page. Since Raphael is a fundamentally visual toolkit, this will take the place of the canonical “Hello World” example in the first chapter of programming books since time immemorial. In case, like me, you never read the introduction, here it is again. read more..

  • Page - 20

    See this code live on jsFiddle. Let’s do a deep dive into this example. Getting Raphael Like jQuery, Google Maps, Backbone, or any other JavaScript library, Raphael is neatly packed in a single external library that you include in your webpage with a <script> tag: <script src="http://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael- min.js"></script> CloudFlare is a read more..

  • Page - 21

    The first argument in the function Raphael() is the id of the HTML element inside of which you’d like to start drawing things. You can pass a variety of elements, but in general a <div> will suit our needs wonderfully. The important point is that Raphael operates inside the cosmos of individual elements on the page. We’re going to cover the ways in which it read more..

  • Page - 22

    Simple enough, right? If you run this code, you should see an empty circle with a thin black border. Let’s not be content with so bland a drawing. To give the circle a fill color and a stronger border, we can assign it attributes, like these: dot.attr("fill", "red"); dot.attr("stroke", "blue"); dot.attr("stroke-width", 3); You can read more..

  • Page - 23

    Wait a minute—if we entered the exact same numbers into the two shape functions, why is the rectangle so much smaller? It’s because the shapes interpret the inputs dif‐ ferently. To an ellipse, the first two arguments refer to the center of the shape and the following two numbers refer to the radii. For a rectangle, the x and y coordinates refer to the read more..

  • Page - 24

    containers, the CSS rules for each of those containers, and the model of the browser. You’ll save yourself a lot of tedium by loading images in Raphael when you need them in some sort of diagram. And of course, you’re not limited to PNGs. Raphael accepts the same types as a regular web page—JPG, GIF, etc. Text To place text on the page, use the .text() method. read more..

  • Page - 25

    inserting \n in the text itself where you want the break to occur. While this can be annoying, you generally want to have exact control over where the text appears on the page and when it breaks onto a new line. For cases where you don’t really want to deal with this, we’ll cover how to borrow a regular HTML element and insert it seamlessly into your drawing. read more..

  • Page - 26

    Transformations There is one attribute, transform , that deserves special attention because of its impor‐ tance and its trickiness. This is a versatile property that can manipulate an object in three ways: rotation, translation, and scale. Let’s begin with a set of three rectangles of different colors: var paper = Raphael(0,0,300,300); var r1 = paper.rect(20, 20, 80, read more..

  • Page - 27

    r3.attr("transform", "R90,140,60"); I’ve added a dotted path here and a yellow dot for the anchor point, just for reference. Likewise, scaling takes two numbers—the ratio of scaling on the x and y axes—and translation takes two for the number of pixels on the horizontal and vertical axis that you would like to move the object: r1.attr("transform", read more..

  • Page - 28

    If you check the output of the console, you will see that the x attribute of the rectangle is still reported as 50, even though the transformation moved the entire shape over to position (80,75). Transformations act on top of the original coordinates, not by modi‐ fying the original values. These basic transformations are pretty straightforward. Where they get tricky is when read more..

  • Page - 29

    var b1 = paper.rect(175, 175, 50, 50).attr({ 'stroke-width': 0, fill: 'blue' }); var b2 = paper.circle(50, 200, 25).attr({ 'stroke-width': 0, fill: 'blue' }); //blank var blank = paper.text(125, 200, "?").attr({ 'stroke-width': 0, fill: 'gray', 'font-size': 60 }); That’s all fine and good, but it’s a lot read more..

  • Page - 30

    See this code live on jsFiddle. You’ll notice my set declarations got increasingly more compact each time as I con‐ densed the syntax. Once you get the hang of Raphael, you’ll be able to save a lot of space by declaring elements and sets and adding attributes all at once, as I did with blue_group . But the verbose way is just fine, too. If you’ve hung read more..

  • Page - 31

    If we were to add a new element to red_group at the end of this little program, we might expect it to be (you guessed it) red. Let’s try adding a square to the end of the script: red_group.push(paper.rect(300, 25, 50, 50)); Bummer. What gives? When you add an attribute to a set in Raphael, it applies those attributes to whatever objects are contained in read more..

  • Page - 32

    If we look closely, we see that the circles were left behind. This is because, as you may recall from a few pages back, circles (and ellipses) use cx and cy for their center coor‐ dinates, not x and y . I have a better idea: all_groups.attr("transform", "T150,0"); Try this out and you’ll see that everything fits perfectly. As we get into more read more..

  • Page - 33

    The Data In the example at the end of Chapter 1, we got a taste of using data to generate the specs of the ellipses and circles. We’re going to extend that concept here by generating the braille patterns for each character dynamically. (I don’t know about you, but I do not feel like manually keying in the definitions for each letter and number by hand.) read more..

  • Page - 34

    "I": "2-4", "J": "2-4-5", "K": "1-3", "L": "1-2-3", "M": "1-3-4", "N": "1-3-4-5", "O": "1-3-5", "P": "1-2-3-4", "Q": "1-2-3-4-5", "R": read more..

  • Page - 35

    "black"); return dot; } Hopefully, the comments explain everything you need to know, but you can try it out with make_dot(3) or make_dot(5) to see how it works. We’re simply mapping digits to spots in a braille letter’s grid. I’ve defined the spacing and radius of the dots in external variables, capitalized by convention to represent constant values, read more..

  • Page - 36

    function make_word(word, pos) { pos = pos || { x: 10, y: 10}; // capitalize word = word.toUpperCase(); var myword = paper.set(); for (var c = 0; c < word.length; c += 1) { // recall that "braille" is the object for the letter definitions if read more..

  • Page - 37

    references to every dot on the screen (grouped into sets for letters and words), which allows us to easily erase the canvas and start over. In the real world, we would probably want to allow users to type something in and see it in braille. No problem: <input id="message" style="width: 200px" value="Raphael is great"/> <input read more..

  • Page - 38

    Final Thoughts: Seeing Things Merely creating an object in JavaScript and calling it a circle does not make this circle appear on the page. All things on a web page, from paragraphs to text to shapes, are represented on the page as nodes or elements, typically as text surrounded by tags. You probably recognize <p>This guy</p> as a paragraph node and <img read more..

  • Page - 39

    Of course, not all objects need a shadow. We could just have easily declared the circle without assigning the output to a variable: paper.circle(50, 50, 20); That’s all well and good, but what happens when we want to update that object with a color and a wider border down the line? We’d have to dig through the page to find it again—a huge pain—or make sure read more..

  • Page - 40

    www.it-ebooks.info read more..

  • Page - 41

    CHAPTER 3 Interaction Chances are good that you aspire to create something beyond the kindergarten-level shapes we covered in the previous chapter. Don’t worry—Raphael handles complex shapes just fine (that was originally the subject of this chapter). But I wanted to skip straight to the interactive aspect of Raphael because it’s what makes the library so in‐ credibly read more..

  • Page - 42

    example, that function read the contents of the input box and translated it into braille. This is extremely convenient for any sort of visualization or graphic where users are invited to slide bars or click buttons to manipulate the number of Raphael objects or their positions. In many cases, however, we want to allow the user to interact with Raphael objects themselves, read more..

  • Page - 43

    I prefer the former method, which uses an “anonymous” function, beca use it’s one fewer variable to deal with. But you’ll occassionally want to declare a function independently and attach it to several different events. It’s mostly a stylistic choice. To make the event a mouseover instead of a click, just use the .mouseover() method: var paper = Raphael(0, 0, read more..

  • Page - 44

    var paper = Raphael(0, 0, 500, 500); var mysquare = paper.rect(25, 25, 250, 250).attr("fill", "red"); var mover = function () { this .attr("fill", "blue"); } var mout = function () { this .attr("fill", "red"); } mysquare.mouseover(mover).mouseout(mout).click(function(e) { this .attr("fill", read more..

  • Page - 45

    var mout = function () { if (!hover_enabled) { return false ; } this .attr("fill", "red"); } </script> Events and Sets Like attributes, events can be applied to sets of objects: var paper = new Raphael(0, 0, 500, 500); var square = paper.rect(200, 10, 50, 70).attr("fill", read more..

  • Page - 46

    what object the user interacted with to trigger the event. We don’t actually use e in the previous example, but I always include it out of habit since it’s so useful. Note that this variable does not automatically exist; you have to pass it to the anonymous function. You can call this variable whatever you like. Most people read more..

  • Page - 47

    itself. This is useful to remember: the mouse events we attach to a shape do not apply whenever the mouse is inside the bounds of that shape, but rather when the mouse is directly interacting with the shape. In addition to .click() , .mouseover() , and .mouseout() , Raphael offers the following events: .mousedown() , .mouseup() , .mousemove() , .dblclick() , and .drag() . That read more..

  • Page - 48

    Here is how we make a draggable circle: var paper = new Raphael(0, 0, 500, 500); var circle = paper.circle(120, 110, 25).attr("fill", "yellow"); circle.drag(dragmove, dragstart, dragend); function dragmove(dx, dy, x, y, e) { this .attr({ cx: x, cy: y }); } function dragstart(x, y, read more..

  • Page - 49

    var paper = new Raphael(0, 0, 500, 500); var circle = paper.circle(120, 110, 25).attr("fill", "yellow"); circle.drag(dragmove, dragstart, dragend); function dragstart(x, y, e) { // save the value of the transformation at the start of the drag // if this is the initial drag, it will be a blank string this read more..

  • Page - 50

    Dragging Sets If you check out the Raphael section of a coding forum like Stack Overflow—what else is there to do on a Saturday night?—one of the most common questions you will see is how to make sets of objects draggable. This comes up all the time with browser games and complex user interfaces. People come up with all sorts of hilariously intricate solutions that read more..

  • Page - 51

    The construction of the die is pretty straightforward save for one small new concept. A .rect() object can take a fifth argument that rounds the corners with a radius of the given number of pixels. Note that we have a white background to the die face as well. It doesn’t make any visual difference so long as the page itself is white, but it makes a huge read more..

  • Page - 52

    I used three anonymous functions there for the sake of variety, but we could actually save a few lines by declaring the functions separately, since the start and end functions are identical. Now let’s get creative! Case Study: Let’s Play Dominoes I always thought the purpose of dominoes was to line them up on their sides and knock them over, particularly if it was read more..

  • Page - 53

    } // first, second, or third column var x = Math.floor(number / 3); // first, second, or third row of that column var y = number % 3; var dot = paper.circle(x * SPACING + SPACING / 2, y * SPACING + SPACING / 2, RADIUS).attr("fill", "black"); return read more..

  • Page - 54

    // function to place piece at x,y location, rotated to angle a (in degrees) var move = function (x, y, a) { pos = {x: x, y: y, a: a}; centroid = { x: pos.x + SPACING * 1.5, y: pos.y + SPACING * 3 }; top.transform("T" + x + read more..

  • Page - 55

    piece.drag(dragmove, dragstart); // rotation piece.dblclick(function(e) { angle += 90; move(pos.x, pos.y, angle); }); There’s no need for a dragend function here since the position is updated each time. The final event handler this function needs is a double click for rotating the piece, and it needs read more..

  • Page - 56

    var dragx, dragy; // drag handlers var dragstart = function (x, y, e) { dragx = pos.x; dragy = pos.y; }; var dragmove = function (dx, dy, x, y, e) { move(dragx + dx, dragy + dy, angle); }; piece.drag(dragmove, read more..

  • Page - 57

    See this code live on jsFiddle. Fire this up and you’ll see 28 beautiful tiles. You can drag and rotate them to your heart’s delight. There is one small improvement I want to make. When objects overlap, the one that was most recently added to the page gets displayed on top; this is known as paint or‐ der. When manipulating a particular tile, we would like it read more..

  • Page - 58

    There isn’t space here to code the rules of the game—also, I don’t feel like learning them—but I would submit that doing so would be easy compared to the hard but fruitful work of making the set. You would probably start by adding a dragend() event handler to snap a piece to the nearest open position on the board, then check the adjacent pieces to see if read more..

  • Page - 59

    CHAPTER 4 Paths: How to Make Custom Shapes and Curves Circles and squares are great for getting started with Raphael, but eventually you will probably want to branch out into something more complex. For that, we will use paths, a relatively simple set of instructions capable of making almost any shape or drawing you can imagine: squiggly lines, donuts, and figure eights, as read more..

  • Page - 60

    For the next shape, you would probably say something like “Start a new shape on the coordinates (15,22)” so that your partner doesn’t accidentally draw a line from the end‐ ing point of the last shape to the new one, Etch A Sketch style. In case you haven’t guessed, your partner here is a computer. Drawing paths in Raphael is an alchemical process of read more..

  • Page - 61

    See this code live on jsFiddle. If you’re fuzzy on why the browser understands #F00 as the color red, read up on “hex‐ adecimal color codes.” Just to see what happens, let’s also add some interior color: mark.attr("fill", "#00C"); Hmmm. Since a Z is not a “closed” figure, in which the last point rejoins the first, Raphael guesses what to fill in read more..

  • Page - 62

    We started at the same point—using a lowercase m here would be meaningless since we don’t have a starting point to be relative to—and then told the computer to move its imaginary pen 50 pixels to the right and zero pixels up, then to the left 50 and down 50, then 50 to the right again. For simple cases like this one, it’s often much easier to use read more..

  • Page - 63

    Again, we can freely mix uppercase and lowercase letters in a path string, though doing so may not contribute to one’s sanity during the creation of complex shapes. Behind the scenes, Raphael stores paths as an array in which each object represents one command of a letter and some numbers. If you were to add the line console.log(tri) at the end of the previous read more..

  • Page - 64

    Polygons Given how common rectangles are in design, it makes sense for Raphael to offer a .rect() function, even if it duplicates what can be done with paths with a few more lines. (Actually, this is a decision baked into the SVG specifications, not a shortcut unique to our library.) It would be highly inefficient, on the other hand, for Raphael to offer a .pentagon() read more..

  • Page - 65

    As you see, a 25-sided polygon is pretty close to a circle, as we might expect. You might even say a circle is a polygon with infinite sides. From there, RaphaelJS will leave you to your musings. Curves Drawing lines that bend and curve is necessarily more difficult in Raphael because you have more decisions to make. So we’re drawing a curve from point A to point read more..

  • Page - 66

    To explore what this means, we’re going to start with a point at [50, 50] and end at a point at [200, 125] . Let’s draw that and make some dotted lines for reference: var paper = Raphael(0, 0, 500, 4000); var starting_point = paper.circle(150, 150, 4).attr({ fill: "green", stroke: 0 }); var ending_point = paper.circle(250, read more..

  • Page - 67

    Whoa. The starting and ending points are the same, and we’re still following the path of an ellipse with the same radii, but we went the long way. The SVG specification calls this the “long arc flag,” but I like to call it the “detour value.” If the detour value is zero or false, the curve takes the shorter path to the destination. If it’s one, it read more..

  • Page - 68

    “clockwise flag.” You may notice that curve 3 “completes” curve 2, since its flags have opposite values. Can you guess what our last combination of flags looks like? If you said “a clockwise flag that takes the long way to get to its final destination,” you were correct: var curve4 = paper.path("M150,150 A100,70 0 1,1 250,220") read more..

  • Page - 69

    See this code live on jsFiddle. As we can see, we have identically sized ellipses passing through the same points, and then rotated. It’s actually a pretty neat geometric property, but I find it difficult to vis‐ ualize. That said, I confess that I have never once found the need to rotate my elliptical curves in the wild. The C Command: Cubic Bézier C urves The read more..

  • Page - 70

    See this code live on jsFiddle. This path begins at coordinates (50,100) and ends up at (250,100), just like a regular old L path. For the first two arguments, I set one control point above the line to the right of the starting point and a second one below and to the left. If I move the first contol point to be below the starting point as well, at the read more..

  • Page - 71

    var cp2 = paper.circle(300, 250, 4).attr("fill", "black"); paper.path(path); Exotic Paths The SVG path specifications contain several more advanced commands for Bézier-like curves that reflect back on themselves. I will freely admit that I’ve never once found a use for any of them. Should you wish to dive in, an understanding of control points is all you read more..

  • Page - 72

    SCALE = 1, HOME_PLATE = { x: 250, y: 350 }, FOUL_POLE = 250; Of course, SVG graphics are meant to scale without us hard-coding a scaling factor. I find it convenient to define one in the code for situations like this, where there is an explicit scale between the screen and a real world object, whether it’s a stadium or read more..

  • Page - 73

    var field = paper.path(foul_line_left + outfield_fence + foul_line_right) .attr({ stroke: "none", fill: "green" }); Looking good so far, though the center field fence looks a little close to me. We can remedy this by extending the second radius in the arc: var outfield_fence = "a" + FOUL_POLE read more..

  • Page - 74

    See this code live on jsFiddle. Beautiful! Of course, a real baseball field is much more refined, with dirt extending in a radius from the pitcher’s mound, grass in foul territory, and so forth. I’ll leave it as an exercise to the ambitious reader to extend this example. The point is, there is nothing about a baseball diagram that you cannot replacate with your read more..

  • Page - 75

    CHAPTER 5 Animations, Part One At some point in your career as a Raphaelite, you will probably discover that, like the Greek sculptor Pygmalion, you are so enamored with your creation that you wish it could become a living being. Pygmalion had to invoke the help of Venus. We only need to use animations. We already have plenty of practice changing the properties of read more..

  • Page - 76

    Fire this up and you will see the red dot travel to the coordinates (100,200) and turn blue over the course of one second. Another thing to note is that animation() is a function attached to the global object Raphael , not a method of the paper instance that we typically declare on the first line of any project. It’s easy to mess this up early in your read more..

  • Page - 77

    Similarly, easing formulas do not alter the total time it takes an animation to complete, only how much progress it has made at incremental points in between. To use an easing formula, you feed the animation a string as its third argument. The default easing formulas are linear , easeIn , easeOut , easeInOut , backIn , backOut , elastic , and bounce . Let’s see what read more..

  • Page - 78

    Imagine how dull Super Mario Brothers would be if Mario and the Goombas took turns moving! Of course, deep inside the machine, everyone is taking turns—we’re not talking about parallel processors here. The effect, however, is of simultaneous movement. Fortunately, Raphael.animate() accepts a function as a final argument that gets called only after the animation is complete. Let’s read more..

  • Page - 79

    theta = c / N * 2 * Math.PI; temp_x = x + Math.cos(theta) * side; temp_y = y + Math.sin(theta) * side; path += (c === 0 ? "M" : "L") + temp_x + "," + temp_y; } return path; } var pentagon_path = read more..

  • Page - 80

    return path; } var pentagon = N2Gon(50, 50, 5, 20); var decagon = NGon(50, 50, 10, 20); var agon = paper.path(pentagon); var anim = Raphael.animation({ path: decagon }, 1000); agon.animate(anim); See this code live on jsFiddle. Much better! That pentagon makes a beautiful transition to a decagon. It works pretty well even if you boost read more..

  • Page - 81

    The idea is to have the ball bounce off the wall. So we have to animate it two times, once to get to the wall, once to get away from it. var ball = paper.circle(50, 50, 10).attr("fill", "orange"); //send it to x coord 290 (the wall is at 300, the radius of the ball is 10) var animToWall = Raphael.animation({ cx: 290, cy: 150 read more..

  • Page - 82

    Once again, that’s much better. But we can imagine it getting tiresome if we have more than one brick wall in there. Fortunately, there is a rather poorly documented feature of Raphael that allows us to pack several stages into one animation. You can accomplish the same thing like this: var anim = Raphael.animation({ "50%": { cx: 292, cy: 150 read more..

  • Page - 83

    'stroke-width': 5, stroke: "#999" }); var weight = paper.path("M" + (x+width) + "," + (y+len) + "h9l3,-18h-24l3,18h12") .attr({ 'stroke-width': 0, fill: '#666' }); /* Next, let's read more..

  • Page - 84

    Let’s see how it looks so far: var paper = Raphael(0, 0, 500, 500); metronome({ x: 125, y: 20, len: 240 }); Slide that weight up and down and you’ll see the tempo adjust accordingly. Now we need to make it play. To do so, we’re going to return a function called play to set off the metronome. This will go at the read more..

  • Page - 85

    }; //2 iterations per animation * 60000 ms per minute / tempo var interval = 120000 / tempo; arm.animate(Raphael.animation(armAnim, interval).repeat (repeats / 2)); weight.animate(Raphael.animation(weightAnim, interval). read more..

  • Page - 86

    To add to this feature, you’d add the function to make the ticking a callback property in armAnim , like so: var armAnim = { "25%": { transform:"R" + angle + " " + (x+width) + "," + (y+len), easing: "sinoid", callback: function () { console.log("tick"); }}, "75%": read more..

  • Page - 87

    CHAPTER 6 Maps, Illustrations, and Other Artifacts I keep promising that Raphael is about more than revisiting memories of high school geometry (something that is always best accomplished with a therapist’s supervision). Right now seems like a fine time to make good on that since we’ve covered all of the core skills for image manipulation. Let’s dive right in to what is, read more..

  • Page - 88

    (We think of Colorado as a straight rectangle, but here it comes from a map that mimcs the curvature of the earth, hence the tilt.) So did I memorize the coordinates for all 50 states and then type them in here by hand? Of course not! Like most good things, this comes from Wikipedia. But we don’t want a map on Wikipedia. We want one on our own website. read more..

  • Page - 89

    var rsr = Raphael('rsr', '959', '593'); var HI = rsr.path("m 233.08751,519.30948 1.93993,-3.55655 2.26326,-0.32332 0.32332,0.8083 ... HI.attr({id: 'HI',class: 'state','stroke-width': '0','stroke-opacity': '1', 'fill': '#000000'}).data('id', 'HI'); var AK = rsr.path("m 158.07671,453.67502 -0.32332,85.35713 1.6166,0.96996 3.07157,0.16166 1.45494,... AK.attr({id: 'AK',class: 'state','stroke-width': read more..

  • Page - 90

    Imperfect though it may be, we can work with this. We can even load it in Internet Explorer 8 and see the SVG we downloaded render in VML. Now that it’s rendered on the page, it has entered our sphere of influence. Manipulating SVGs Found in Nature There are a few things I don’t love about the raw JavaScript we get from ReadySetRa‐ phael. It takes the read more..

  • Page - 91

    I suppose we could take all that JavaScript from ReadySetRaphael and perform an elab‐ orate find-and-replace command. As a rule, I like to avoid this sort of thing because it’s tedius and it’s hard to remember how to do the next time. Once again, there’s a Raphael command to help out. It’s called .setStart() , and until this very moment I never thought I’d read more..

  • Page - 92

    I see two problems. There are some strange triangles getting filled in around Hawaii and Alaska. Also, all of the states are in the wrong place. These are both problems we can handle. Those rogue lines are pretty easy to find in the source from ReadySetRaphael since they don’t have a proper name: var path57 = rsr.path("m 211,493 v 55 l 36,45 M 0,425 h 144 l read more..

  • Page - 93

    that every number is associated with a two-letter state abbreviation. Believe it or not, the United States government doesn’t offer the information in a neat JSON format, so I copied the information from BLS by hand and delimited it with a | character. There are better ways to do it, but this is fine: var rates = {}; // split the data into tab-delimited pairs read more..

  • Page - 94

    The only thing I see wrong here is that Michigan’s Upper Peninsula has seceded from the United States. ReadySetRaphael got a little confused here and gave it the id SP , for what, I have no idea. Change that data value to MI and you’ll be just fine. I’ll spare you yet another screenshot. See this code live on jsFiddle. Interlude: Raphael vs. D3 What we’ve read more..

  • Page - 95

    For that, I’d like to introduce a handy Raphael function called .hsl() , which stands for “hue, saturation, lightness.” It’s an alternative to the more common RGB system of rep‐ resenting colors in the browser, and accepts three values from zero to one. It’s convenient for us here because we can create a range of colors for our selector in a loop. This is read more..

  • Page - 96

    This modest tool leaves something to be desired (like black, white and gray), but it’s not bad for a minute’s work. Now we’re going to add an SVG from the Internet. I’m choosing a picture of a scien‐ tist from Clker, my favorite royalty-free clip art site, but you can choose absolutely any SVG you want. After running the SVG through ReadySetRaphael, we need read more..

  • Page - 97

    CHAPTER 7 Animations, Part Two The animations we covered in Chapter 5 were basically ways of delaying our hard work. By feeding attributes through an animation, we instruct Raphael to take its sweet time altering the appearance of an object instead of changing it all at once. That suits us just fine a lot of the time, but it can get dull. When moving an object to read more..

  • Page - 98

    Adding Functions To add a function, assign a function to Raphael.fn as though it were an object (which it is): Raphael.fn.NGon = function (x, y, N, side) { var path = "", n, temp_x, temp_y, angle; for (n = 0; n <= N; n += 1) { console.log(n); angle = n / N read more..

  • Page - 99

    paper.circle(50, 50, 20).attr({ redness: 25, 'stroke-width': 3 }); Adding Methods The third and final means of extending Raphael is to create methods that act on ele‐ ments, the way toFront() rearranges an object in the DOM or remove() deletes it. Here’s a function that makes an element more red than it was before: Raphael.el.redder = function () read more..

  • Page - 100

    var dx = x + 2 * rx * Math.cos(theta), dy = y + 2 * rx * Math.sin(theta); path += "A" + rx + "," + ry + " " + angle * c + " 1,1 " + dx + "," + dy; path += "A" + read more..

  • Page - 101

    // don't worry about 'alpha' just yet circle.attr({ cx: point.x, cy: point.y }); See this code live on jsFiddle. As you see, the red dot landed neatly on the rosetta at the right point. All that’s left is to animate it, though this is a tad trickier than it might seem. Remember that we have to animate properties like fill or transform . We read more..

  • Page - 102

    See this code live on jsFiddle. This successfully places the red dot 30% of the way along the complete path of six ellipses. (I originally tested it with 0.5, thought it didn’t work, then realized that the 50% point along the path is the dead center.) Now that this is working, let’s give it a whirl with a nice long duration of 10 seconds. read more..

  • Page - 103

    var shape = paper.rect(0, 0, 20, 10).attr("fill", "green"); shape.data("mypath", rose); shape.attr("progress", 0); shape.animate({ progress: 1 }, 10000); As a final feature, perhaps we might like to draw the path as we go instead of mapping out the course of the path ahead of time. If you’re old enough to remember Logo, the old read more..

  • Page - 104

    provide every possible tool, Raphael gives you just what you need to whet your imagination. But you probably don’t want to write a lot of code for every project. If any function you write seems useful and elegant enough for wider use, by you or anyone else, the .fn , .el , and .customAttributes functions allow you to store them in a JavaScript file and sum‐ mon read more..

  • Page - 105

    If you’re more of a visual thinker, here’s a graph of the progress of the animation as a linear easing and an easeIn easing: It’s not a law of nature that the easing formula must neatly end up at a value of one. If it doesn’t, however, you’ll see an awkward skip at the very end as it jumps to its desti‐ nation. (Remember, Calvinism: it ends up read more..

  • Page - 106

    Give it a shot and you’ll see the red square zip most of the way to its destination, change its mind and backtrack, and then get with the program and speed up to reach the final point on time. Here’s one that makes the square scatter around: Raphael.easing_formulas.may_cause_seizures = function (n) { return n + 0.2 * Math.random() - 0.1; }; read more..

  • Page - 107

    var paper = Raphael(0, 0, 500, 450); //http://nineplanets.org/data.html var orbits = { Mercury: { distance: 57910, period: 87.97, eccen: 0.21 }, Venus: { distance: 108200, period: 224.70, eccen: 0.01}, Earth: { distance: 149600, period: 365.26, eccen: 0.02}, Mars: { distance: 227940, period: 686.98, read more..

  • Page - 108

    // Also get focus from eccentricity of orbit // http://nineplanets.org/help.html#semim var perigee = data.distance * (1 - data.eccen) * ORBIT_SCALE, apogee = data.distance * (1 + data.eccen) * ORBIT_SCALE, focus = data.eccen * apogee, x = CENTER.x + focus - read more..

  • Page - 109

    See this code live on jsFiddle. And there you have it: your second grade art class homework is complete. Code Example: The Animated Solar System | 97 www.it-ebooks.info read more..

  • Page - 110

    www.it-ebooks.info read more..

  • Page - 111

    CHAPTER 8 Mobile, Global Variables, and Other Things That Hurt Less Than You Think Up until about a year ago, my strategy for dealing with people with mobile browsers was to pretend they didn’t exist. This worked reasonably well. Alas, times change. The number of viewers accessing a site from a phone or tablet varies dramatically de‐ pending on the type of site. For read more..

  • Page - 112

    Measuring the Container Let’s freshen up on dynamically resizing containers. The easiest way to do this is to use CSS to set the width of a block-level element, like a regular old <div> , to 100% (or any other percent you like). You can then measure the width of the element by finding it with JavaScript and re‐ trieving the offsetWidth property. <style> read more..

  • Page - 113

    Assigning a function to window.onresize overwrites other functions already attached to this event, which can cause problems on pages using other libraries as well. It’s best to use jQuery or at least be very mindful of what else might be sensitive to page resizing. Let’s put some stuff on the page to experiment read more..

  • Page - 114

    } resize(); window.onresize = function () { resize(); } Now that we have this resize function set up, we’re going to use a Raphael method called .setSize() to dynamically resize the canvas: function resize() { var w = document.getElementById("canvas").offsetWidth; paper.setSize(w, 200); } See this code live on jsFiddle. Fire that up and read more..

  • Page - 115

    phase = (phase - 0.5) * 2; // left arc var path = "M" + opts.r + ",0"; path += "a" + opts.r + "," + opts.r + " 0 0,0 0," + opts.r * 2; var clockwise_flag = phase > 0 ? 0 : 1; phase = Math.abs(phase); read more..

  • Page - 116

    return { setPhase: function (new_phase) { orb.attr("path", shape(new_phase)); } } } Okay. Try it out if you don’t believe me. To make the logo, we could use Raphael’s .text() function to draw all the letters other than the two O’s. But I don’t particularly like text in read more..

  • Page - 117

    r: 18, phase: 0.75 }); </script> Ta-da! I would eat here every day. (There is actually a restaurant called Paper Moon where I live, but all I remember about it is that I spilled tomato sauce on my tie.) See this code live on jsFiddle. Stealth Raphael The above example may seem like a laborious way to demonstrate that Raphael can accept the id read more..

  • Page - 118

    for (var c = 0; c <= 1; c += 0.1) { var m = moon({ el: paper, r: 20, phase: c, x: c * 420, y: 0 }); } See this code live on jsFiddle. What this also means is that, because the function falls back on making its own read more..

  • Page - 119

    drawn in libraries as you need them (the way you might in Python or NodeJS), you’re playing with fire if you start mixing and matching a lot of third-party code. Raphael has a small global footprint, so it’s pretty safe. But to be extra cautious, you can use it’s “ninja” mode to condense it all into one global variable, Raphael . Other libraries, like jQuery, call read more..

  • Page - 120

    After saving this file as something like code.js , you would run this: browserify code.js > script.js The script.js file now contains the Raphael source code and the above. As a bonus, it automatically runs inside a function, so circle , paper , and whatever else you declare will not find their way into the global namespace. Final Thoughts: The Future of Raphael and You As read more..

  • Page - 121

    About the Author Chris Wilson is a journalist and developer at Time.com. Prior to joining the magazine, he was a “visual columnist” at Yahoo News and a senior editor at Slate, where he founded Slate Labs, which won the 2010 Ad Age Media Vanguard Award. He is a 2005 graduate of the University of Virginia and lives with his wife Susan in Washington, D.C. read more..

Write Your Review