Doodle-js

Gentle reader, this page demonstrates a depreciated version of Doodle.js. Check the landing page or GitHub page for up-to-date examples, information, and code.

I’ve been having a lot of fun with the HTML Canvas element and really look forward to utilizing the next-gen Javascript engines the browsers are starting to roll out.

However the drawing commands for it are a bit… basic. It can be difficult to work creatively when you have to constantly handle the “low level” details — that’s why I wanted to create a library that did it for me. Doodle.js attempts to create a fun and easy way to interact with the Canvas that is lightweight, flexible, and functional. While it contains a few shape primitives it is not meant to be a full-fledged drawing api, rather a framework that allows you to build sprites and interact with them in an expressive way.

This is a 0.1 development release so please treat it accordingly. Bugs are sure to crop up so it’s best to test things out with your browser’s debug console open. I’ve been trying it on Chrome, Firefox 3.0.8, and IE 8 (using excanvas).

Here are a few demos I put together that you might want to take a look at before reading on.

Demo source available here.

This is the setup for a basic HTML file that we’ll use for the rest of the examples. You’ll see that it includes a link to excanvas.js (for IE) and the Doodle library. In the body of the document we have a canvas element with an id of “my_canvas”. If your browser doesn’t support canvas then some fall back content will appear instead.

With the basics in place we can add some Javascript to draw a square.

D1

To avoid cluttering up the namespace, when you import the Doodle library it will create a single global object named $doodle . Everything in the library can be accessed through this variable, but to save some keystrokes we’re going wrap it up in anonymous function call using a popular Javascript idiom.. The “oo” variable was picked because it’s easy to type, easy to remember (d-oo-dle), and easy for our eyes to parse when we look over the code (it only takes a very cursory knowledge of male psychology to understand that).

Now that we can access the library, we’ll first feed it the id of our html canvas. We then create a rectangle with oo.rect() by passing it a Javascript object that contains our named parameters. We want a square 50 pixels wide that is situated at the coordinates (25, 25), which starts from the top-left point of our canvas element. Finally we render the rectangle to the canvas element by making a call to .draw().

Pretty easy eh? Well let’s say we want to draw our little box again, this time starting exactly in the middle of our first box. Let’s take a look:

D2

So what did we do here? You’ll notice that we made a call to .draw() twice, but unlike our first example where .draw() ends with a semicolon; we omit that and instead make a call to the objects .modify() method. We can do this because the methods of a doodle object return the same object that called it. This allows us to chain functions together creating complex behavior in relatively few lines of code.

Now how do you reference a value from an object that hasn’t been created yet? (Well the object has been created, it just hasn’t been assigned to a variable yet.) Once inside the .modify() method we demonstrated two ways of referencing our previously declared values. With the x property we pass it a string (surrounded by quotes) and start it with the relative assignment operator “+=”. This adds 25 to what was previously stored in x (25), so now x holds the value of 50. It’s important to know that Doodle knows quite a few of these relative assignment operators, but you can’t simply pass any code here. This code is not being evaluated in a Javascript sense (that’d be dangerous), instead it’s just looking for the operator. Also note that it does not support passing variables here.

When we modify the y property we are passing it an anonymous function that is called with itself as the arguments and the return value is assigned back to y. This is a very flexible and powerful way to in-line functions and return the results of any equation. The function is called from within the object, passing itself as the first argument, in this case assigned to “o”. The second argument is the property you are modifying, in this example “p”. You don’t have to use these but they are there for convenience. Finally we change the fill color to blue and then make a call to .draw() a second time. So we’ve created a box, drawn it, moved it, then drawn it again. Keep in mind that this is the same box, not a separate object, so we can’t change the order they appear on screen after they have been drawn. For that you’d need to create 2 separate objects and assign them to a new group: oo.group().add(box1, box2).draw(). The order they are drawn depends on the value of each object’s “z” property.

Transforms

All transformations to an object are represented as a 2d matrix and stored in it’s obj.matrix property. If your interested about how they work I will point you to a nice tutorial on the subject. Doodle objects support a number of methods for transforming it’s matrix: translate, rotate, scale, transform — or you may operate on the matrix itself.

D3

In this example we have created a box and drawn it 5 times, changing it’s color each time to better illustrate the effects of the applied transforms. Our box is first drawn at an initial position of (25, 25) and given the color red (in hexadecimal notation).

We then change it’s color to green (this time in rgb notation), move it right 50 pixels on the x axis and draw it again. Next, we change to purple and rotate 45 degrees before drawing again. Notice it rotates around the default axis point which is it’s top-left point, or in local space at (0,0). [This would correspond to it’s position in global space on the canvas which is now (75, 25).]

Next we perform 2 transformations by chaining them together. First we move the box 50 pixels along it’s now rotated x axis. We then multiply it’s scale by 1.5 along it’s x and y (the single parameter we passed here is short for .scale(1.5, 1.5) ) and draw the now yellow box. Finally, we change it’s color to blue, and do the same thing as we did in the previous line — translating 50 pixels on x and increasing it’s scale by 1.5, the difference being that we are now applying the transform at the same time by using matrix notation.

Loops

To loop over an object you must give it some parameters to change — otherwise it will continue to write the same thing over and over again, looking like a static image. In this example we will draw a circle at the center of our canvas, then draw it 24 more times rotating around this point — each time adjusting it’s position and assigning it a random color. We’ll do this with a traditional “for-loop” to start and then look at some built-in methods for accomplishing the same task.

D4

Now we’re going to draw the exact same thing except we’ll utilize the object’s built-in .loop() method. It’s up to you which way you feel comfortable with, but this is a more functional way of doing things if you’re into that sort of thing. It also demonstrates some of the flexibility you have when assigning values to object properties in Doodle. You’ll notice that the first dot.draw() call has been omitted in this example. The reason is a .loop() takes a modification parameter that will be assigned on subsequent iterations. Meaning the first call to loop will always draw the object in it’s current state, additional loops will apply the modifications. There is also a special property in the loop parameter object, .on_update. This is a function that will be run after each iteration of the loop allowing you to increment variables or alter properties. You could modify everything from within this function if you really wanted to, but that might be a bit confusing.

Another option for the .loop() method is to pass it a function instead of an object and to use .modify() within it.

Now let’s take a look at this loop:

This loop runs indefinitely and will completely clear the canvas every 800th frame. We’ve added a framerate parameter to the loop which dictates how fast it’s run; this can take a numeric value in the measure of milliseconds or as we can see here as a string with “fps” appended.

In this loop we are starting to get an idea of the animation capabilities inherent. By changing the count to zero and setting the clear every frame parameter to true we can put our little circle in motion. In fact all sprites have an .animate(params, framerate) method that is just a .loop() that runs forever and clears every frame. Animation is very experimental at this point, especially when working with multiple objects since clearing the canvas will have conflicts. A safer way is to use the global animate function in Doodle:

Images

You can import images and draw them as normal shapes. Though since they take time to load it can be a little tricky sometimes having them interact with the rest of your program. You can pass a function to it’s on_load parameter that will be called when it’s ready to use. The below example worked fine for me in Chrome and Firefox, but unfortunately I’ve had difficulties in IE applying matrix transforms to images.

Custom Shapes

Doodle is not meant to be a full-fledged drawing library, rather a way to better group and organize your own shapes. To that end it’s easy to create custom objects and assign them shapes using the canvas drawing api. We’ll use the $doodle.gfx object to access these commands and assign them to the shape function of an extended sprite object.

Groups

Objects can be grouped together and transformed around a common axis. The order an object is drawn in a group is determined by it’s z property. A higher number means it will appear “on top” of another object. You can change the way a group composes it’s objects by assigning a composite operation to the group.composite property. A list of these can be found here. Groups haven’t been fully implemented yet, so your mileage will vary.

Interaction

To get the mouse coordinates I find it easiest to use jQuery, but you could use any of the great Javascript libraries out there.

Conclusion

Like I said before, this is the first development release so I’m still hunting bugs. If you find something and can help out, please shoot me a message. I’ll get some more extensive docs once the API settles down, until then just punch around the source code.

Posted

Emacs todo-list-mode

On GitHub.

Todoem

Although it wasn't on my todo-list, I really had a hankering to add some auto-color highlighting to mine. So I created a pretty basic major-mode for Emacs which I call todo-list-mode. My list is just a plain text file that I can sort the lines based on the assigned number in the first column. I created a few regexp's to pick out these and change the formatting based on priority. It's pretty simple and easy to extend, so if you want to add more numbers or change the colors - go nuts. It also supports hash style comments to tack on the end of a line.
Grab it: todo-list-mode.el

To include this mode automatically, add to your .emacs :

The format for a given line is: number (0-4), [optional lower case letter], [TAB], task text. If you want to add more numbers, change the colors, or change the delimiter, it's fairly easy to open up the elisp file and do a little copying and pasting.

To sort I just use some standard Emacs commands; Select a region (C-x h for entire buffer), then M-x sort-lines . To note, the regular expression that does the coloring looks for a tab delineator between the priority number and the task text. If you'd rather not use tabs you'll have to change it to a couple of spaces or something.

This style works for me because I really need something minimal and easy to access if I'm going to use it. Sure there's org-mode and other more complicated variants but I need simplicity. There's too many other things to worry about that I can't justify spending extra brain activity trying to operate a todo list. This ordering system is something I got from Randy Pausch, which is based on Stephen Covey's quadrant system.

Posted

3D Flash Demo, "Strain of Control"

A typographic demo combining physics and 3D. A more creative variation on the PaperBox2D method I demonstrated here.

Posted

Papervision3D + Box2D

In a recent project I wanted to incorporate some physics with a 3D environment. I decided on Box2DFlash, which is a great engine even if the syntax is a little awkward for an Actionscript 3 library.

See the PaperBox2D Demo, and the source is available. Hit the 'd' button during the simulation to toggle the debug regions for the 2d calculations and see how they are mapped to the objects in 3d space.

Updated 11.20.08, recent api changes in Box2DFlash.

Posted

Type Around the Neighborhood

I brought my camera along for my daily constitutional and decided to take in some of the local signage. Gill Sans (aka "England's Helvetica") seems to be a popular typeface around Buffalo, which is fine but can be a bit tiresome. Kinda like a girl you had a fling with once and for some reason keeps popping up - you don't really regret anything, but you'd rather try something else.

Posted

Better Bend Than Break

Another Papervision3D demo, this time manipulating a vector image.
Source code available.

Libraries used:
VectorVision
AS3Dmod

Posted

3D Flash Demo, "Arrive"

Well I just finished a little interactive demo using Actionscript 3, Papervision3D, and some models I created in Maya. I used a song by Ehma who in his infinite wisdom released the music on Jamendo. I suggest you to check it out, it's nice!

Posted

3D Flash Demo, "See Through"

The Papervision3D guys are running a nice little contest so I thought this would be good chance to show an example of some of the recent stuff I’ve been working on. Here’s the demo, and here’s the source code. Read on for more detail about the code and some of the inspiration.

First a word on the inspiration. I come from a photography background so it shouldn’t come as much surprise that in my design work I tend to think of things like a photographer — using space, composition, and cameras. This is why engines such as Papervision3D are exciting to me; they give me a chance to combine all of my interests in photography, graphic design, and programming into one medium. There are also a lot of parallels between programming and photography, namely that they are both fairly technical and require a bit of pre-visualization. The majority of your effort is spent constructing an implementation towards that imaginary goal — manipulating code very much like manipulating light to achieve a photograph. So with those similarities in mind I wanted to highlight the use of light in this demo. I also began thinking of the physical design of cameras themselves and some of the old classics. It almost seems silly that the machine designed to create art becomes a work of art itself, but this happens with code as well. Things of such complexity can be studied and studied creating their own following. So looking around flickr for old cameras I came across a picture of this little gem…

Kodakgift

One of Walter Dorwin Teague’s modernist designs for the “Gift No. 1A” during his time at Kodak (a Western New York icon btw). Quite the sporty little accessory to have around your neck in the early 1930’s. This became a good place to start laying out the scene’s look and structure.

The Code

More than likely you’re visiting this page and could probably care less about any background inspiration and want to see how the example works. As I mentioned before, the source code is available so I won’t go through everything, but just highlight some of the more trickier issues.

In a nutshell this scene is just a collada model that I exported from Maya and baked textures onto. Papervision is a fantastic 3D engine but since we are working in a browser with Flash we are very limited by what a software renderer can do. With that in mind we have to create a very low-poly mesh and reduce our triangles count as much as we can. (Pop quiz, what do 3D modeling and type design have in common? Both require that you achieve the maximum expression of a shape with a minimum amount of points.) But, and this is a big but, when modeling the ground and wall planes you’ll be tempted to get rid of all the extra polygons — this is a mistake. We need those extra polys to hold the texture position correctly. [If we didn’t we could turn on precision for the material, but that would slow everything up.] So you may want to do some experimenting with count versus performance, I found a 10 x 10 plane to be a satisfactory compromise.

Another concern in the modeling stage is how the objects are grouped. Before you export your model be sure to combine the meshes you want as one texture and give it an easy name to remember (simply grouping the objects is not enough). This will make it more convenient when assigning your model parts to separate viewport layers later on. Apply a simple lambert shader to the objects and change the shaders name, it’ll be quicker to locate when you’re searching through the collada xml later.

Model, light, render, bake, and export your textures as you normally would. Make sure your models have been UV mapped and keep in mind your textures should be 512 x 512 (1024 if you really need it) for performance reasons.

When loading the images as materials you’ll need to replace the shader name that it’s given within the collada xml. Doing a search for “instance_material” will give you something that looks like:

You’ll be looking for the symbol name that we’ll add to the material list so we can swap in our texture:

Now we still may get flickering polys with the model and the ground plane. This is a z-sorting issue that we can fix by using Papervision’s ViewportLayers. Andy Zupko has a much better explanation of using them with effects so I won’t repeat that, I’ll just show the relevant parts in my code:

The names “floor” and “words” are the names I gave the objects when I combined their meshes earlier. Since in my demo I wanted to simulate caustics I needed to make the model a little transparent. Since you can’t adjust the alpha of a BitmapMaterial I added the model to a separate viewport layer and adjusted it’s transparency there. And since both the floor and the words are being rendered on separate layers we can eliminate the “z-fighting”.

Well I hope that helps someone. The Papervision team are doing a fantastic job but you’ll need to help yourself as well. It’s up to careful modeling and texture optimization that will give you the biggest performance gains.

Posted

ActionScript3 in a Flex Component

Using an Actionscript class within a Flex component can be a little tricky. The first error I ran into was:

This was a result of using a stage reference within the class to set up boundaries. Since I no longer had access to the stage properties I created two variables within the class to pass the Flex canvas size on instantiation. The second error I encountered was:

This is because the Flex component will only accept a UIComponent as a child. Since our Actionscript class extends a Sprite we'll need to place it within one first:

This creates a reference UIComponent that we will place our BouncingBall class into which we can now add to our canvas. An alternative method is to use the rawChildren of the canvas and add the sprite directly to it's display list. While this works fine, it does seem a bit obscure/ugly. But whatever floats your boat:

The MXML is rather straightforward, though you'll want to include a clipping rectangle on the canvas otherwise the ball will be dragged all over the screen. The source code for the above example is available here.

Posted

A Brief History of the Hyperlink

(And Why We're Not There Yet)

There's a fascinating article in the New York Times today about Paul Otlet, who in 1934 sketched out plans for a network of computers that would allow people to search through a global archive of interlinked documents. Though his system at the time was just a mechanical, albeit very robust card catalog; he foresaw the age of electronic media storage when one could sit comfortably at his desk and peer into data collections around the world through "electronic telescopes" (I just love that term).

Aside from a little forgotten computer lore his story highlights the most fundamental underpinning of the Internet and perhaps the most important invention of the modern age - the hyperlink. As we surf our favorite blogs and forums, it's easy to take for granted the ability to instantly navigate from within one document to another. But the idea and it's implementation have it's own interesting histories and failings - with hypertext it's important to know not only where you went, but how you got there.

What happens when a link becomes its own document? How was the hyperlink envisioned and then implemented, and perhaps more important - how can it be improved?

H1
In 1945 Vannevar Bush wrote an essay titled As We May Think which argued that as humans turned away from war, science should also turn from increasing physical abilities to making knowledge more accessible. In it he described a theoretical machine called a "memex" (memory extender) which would enhance human memory by allowing the user to store

 and retrieve documents linked by associations. Bush described a microfilm-based machine in which one could link any two pages of information into a "trail" of related information, and then scroll back and forth among pages in a trail as if they were on a single microfilm reel. The essay predicted technologies such as personal computers, the Internet, online encyclopedias and speech recognition. The latter expressed his fundamental view that computers would interact with man, and also highlights his lack of understanding of the complexities of information science and the human-computer interface. In fact it would be human beings who would change their behavior to interact with a rigid machine using unnatural inputs such as a keyboard and mouse pointer. By the time technology can accommodate such things as fluid speech and movement interaction, our "natural" inclinations may well have already changed.

H2
It was from As We May Think that inspired Ted Nelson in 1965 to first coin the term "hypertext". It was for his Project Xanadu which had the goal of "facilitating non-sequential writing in which the reader could choose his or her own path through an electronic document." This system was built on top of work he did as a graduate student developing a less lofty idea, but perhaps more practical one - a word processor capable of storing multiple versions, and displaying the differences between these versions. That Project Xanadu didn't even release an (incomplete) implementation until 1998 shows how far that dream came, nonetheless, the idea and vision were already set in motion.

In 1966 a team at the Stanford Research Institute lead by Douglas Englebart first implemented the practical use of the hyperlink in their NLS "oN-Line System", first for scrolling within a single document and later connecting between paragraphs in separate documents. This thing must have been a damn wonder to behold at the time, the NLS system used a mouse (co-invented by Englebart), had video monitors, screen windowing, and presentation programs. In 1968 they demonstrated it's features at a computer conference in San Francisco, which has become affectionately known as "The Mother of All Demos". It was the first time the public saw a mouse, introduced interactive text, teleconferencing, video conferencing, email, and of course the use of hypertext. Good thing I wasn't around in 1968 or my head would have exploded:

A true marvel of the twentieth century whose fatal flaw was that it was next to impossible to actually use. It made heavy use of "programming modes" and you had learn cryptic mnemonic codes to do anything useful. And if you didn't want to use a keyboard you had to learn 5-bit binary code, which just sounds like a pure joy to learn I'm sure. Eventually many of the top researchers left and ended up at Xerox PARC taking the mouse idea with them.

H3
So fast forward to 1989 when an English computer scientist working for CERN by the name of Timothy Berners-Lee saw an opportunity to join hypertext with the Internet. "I just had to take the hypertext idea and connect it to the Transmission Control Protocol and domain name system ideas and *ta-da!* the World Wide Web." Oh that's all? Since then he's been working to develop Web standards and been knighted by the Queen. And I guess you can thank him for being able to read this blog now.

But Is That It?

When you look back upon the history of the hyperlink you start to appreciate the idea of the hyperlink. It is unfortunate that what we have today is a rather "dumb" version of it, carrying little more than a destination address. Paul Otlet envisioned a smarter kind hyperlink that could for example, carry information annotating if particular document agreed or disagreed with each other. With something so integral to the fabric of the World Wide Web what are we doing to improve the idea? Proponents of the "Semantic Web" argue for attaching more metadata to links, using such microformats as XFN to represent social relationships and Geo to specify geographical coordinates. These markup languages may be easily parsed but they serve computers more than humans. The real question may be one of design rather than a solely technical solution, not "what information will we embed in the link?", but rather "what will it look like?" Currently there are too few visual indicators to convey meaning for hyperlinks, with the most prominent being a color change to denote a page that you've already visited. But what other relationships can be represented? There's a wide range of possibilities, what visual, aural, or tactile tools are at our disposal?

Perhaps we should look less at hyperlinks as the movement between documents, but rather as the documents themselves.

Posted