Canvas

Canvas is a little suite of tools to help you do stuff with Walter Zorn's jsGraphics library. The Canvas class lets you add canvasses to documents dynamically with ease. The CanvasSet class lets you draw in multiple opacities in a snap. The JsSprite class lets you implement sprite-like sets of drawing instructions that can then be repeated at different locations (thus optimizing CPU, if the calculations were initially math-intensive), and hopefully some day, rotated. Contributions welcome, particularly where it comes to filling out features like rotation or anything else you can imagine.

Compatibility

Canvas has been tested on Firefox 1.5, 2.0, and IE 7.0. It should work on any platform that jsGraphics does, but I can't know that for sure.

License and responsibility

You can use this library for anything you want without restriction. It would be nice if you provided proper attribution of this code back to this site. I developed this library for use with the applications I'm working on at Tabblo, who were nice enough to allow me to distribute this code. Your use of this code comes with the understanding that I cannot promise it will work and I cannot promise it won't hurt projects that rely on it in any way. Since I cannot promise this, your use of the code comes with the understanding that I am not directly or indirectly liable for any results of your using this code, and nor is Tabblo responsible or liable in any way.

Examples

Let's use the Canvas library to make a canvas, and then do some stuff with it. I'll proceed by displaying code fragments, then links that will excecute the code. The 'Canvas' object is here initialized with a position spec ('x,y+w+h'), a parent to locate itself (any false value in JavaScript results in document.body as the parent), a bgcolor, an opacity, and a z-index ("auto" is supported).

    // create a new canvas at position 500 (x), 500 (y), width 200 and height 200, 
    // whose parent is the document.body, bgcolor of #cccccc, opacity of 0.8 ([0-1]), 
    // and z-index of 9999:
    var canvas = new Canvas("500,500+200+200", "", "#cccccc", "0.8", "9999");
    // render the canvas to the screen:
    canvas.render();
    // draw a line on this canvas:
    var g = canvas.graphics;
    g.drawLine(0, 0, 200, 200);
    // change the stroke and color
    canvas.setStroke(2);
    canvas.setColor("#ffff00");
    // draw another line
    g.drawLine(200, 0, 0, 200);
    // and paint
    canvas.paint();

Execute.

Now, we're going to make a new canvas, but instead of manually setting up its properties, we'll fit ourselves into another object on screen. The 'Canvas' object is here initialized with an positioned DOM element to 'mock' (copy its width, height, position), a parent to locate itself (any false value in JavaScript results in document.body as the parent), a bgcolor, an opacity, and a z-index ("auto" is supported). (My examples do not include one where I manually set up a parent other than document.body for the actual canvas, but you can imagine a case where that would be necessary; for example, if 'canvas_me' was located inside a positioned DIV, then you'd want to use that DIV as the canvas' parent; otherwise, the resulting canvas will not necessarily be placed exactly where you want it.)

A div called 'canvas_me'.
    // create a new canvas with the same properties and position 
    // as canvas_me, whose parent is the document.body, bgcolor 
    // of #cccccc, opacity of 0.8 ([0-1]), 
    // and z-index of 9999:
    var canvas = new Canvas("canvas_me", "", "#cccccc", "0.8", "9999");
    // render the canvas to the screen:
    canvas.render();
    // draw a line on this canvas:
    var g = canvas.graphics;
    g.drawLine(0, 0, 200, 200);
    // change the stroke and color
    canvas.setStroke(2);
    canvas.setColor("#ffff00");
    // draw another line
    g.drawLine(200, 0, 0, 200);
    // and paint
    canvas.paint();

Execute.

Now for a more interesting example. We're going to create a CanvasSet with a list of opacities, and then render a bunch of stuff on each 'layer' of the result. We initialize 'CanvasSet' very similarly to a Canvas, but with a list of opacities instead of just one. We pick which canvas to draw on by calling setContext() with the opacity layer we want to draw on (defaults to the highest opacity layer).

A div called 'layer_me'.
    var canvas = new CanvasSet("layer_me", "", "", 
                 [1.0, 0.8, 0.6, 0.4, 0.2], "9999");
    // render the canvas to the screen (renders all 
    // interior canvasses):
    canvas.hide(); // hide everything in this canvas set
    canvas.show(); // show everything in this canvas set
    // draw a line on this canvas:
    var g = canvas.setContext(1.0);
    g.drawLine(0, 0, 200, 200);
    // change the stroke and color
    // using canvas.setcolor instead of g.setcolor sets 
    // the color for all graphics contexts in this set
    // similarly for setstroke
    canvas.setStroke(2);
    canvas.setColor("#ffff00");
    // draw another line
    g.drawLine(200, 0, 0, 200);
    // set another context
    g = canvas.setContext(0.8);
    // draw more stuff, etc.
    g.fillRect(4, 4, 40, 40);
    g = canvas.setContext(0.6);
    // of course, you can also continue to set color 
    // directly on the graphics object
    g.setColor("#dddddd");
    g.fillEllipse(10, 10, 60, 90);
    g = canvas.setContext(0.4);
    g.fillRect(20, 5, 90, 40);
    g.fillRect(90, 90, 40, 80);
    g = canvas.setContext(0.2);
    g.setColor("#dd0000");
    g.fillEllipse(0, 0, 150, 180);
    // and paint (paints all interior canvasses)
    canvas.paint();

Execute.

Sprites are a fun idea. Here is a very trivial implementation. You write the drawing instructions into the sprite, instead of directly into the graphics context. Then you render sprites to the graphics context.

A div called 'sprite_me'.
var example_canvas = null;
var s = null;
function setupSprite()
{
    // a new sprite with origin 0, 0, and rotation 0 
    // (I have not yet implemented 
    // rotation logic; placeholder only)
    s = new JsSprite(0,0,0);
    // start writing into the sprite; 
    // in this case, it's an arrow with a square at the end
    // granted, getting the function references here 
    // is ugly (I'm getting them from a particular 
    // graphics context -- but I avoid this for render 
    // because I have to); need a better way someday
    s.addInstruction(example_canvas.graphics.drawLine, 
                      10, 10, 90, 10);
    s.addInstruction(example_canvas.graphics.drawPolyline, 
                     [75, 90, 75], [5, 10, 15]);
    s.addInstruction(example_canvas.graphics.fillPolygon, 
                     [95, 215, 215, 95], [5, 5, 15, 15]);
}
function example4(x, y)
{
    if (x == 0)
    {
        // create a new canvas at position 
        // 500 (x), 500 (y), width 200 and height 200,
        // whose parent is the document.body, bgcolor 
        // of #cccccc, opacity of 0.8 ([0-1]), 
        // and z-index of 9999:
        example_canvas = new Canvas("sprite_me", "", "#cccccc", "0.3", "9999");
        // render the canvas to the screen:
        example_canvas.render();
	setupSprite();
    }
    s.paintAtLocation(example_canvas.graphics, x, y);
}

Execute 0, 0. | Execute 20, 20. | Execute 40, 40. | Execute 10, 80.

Download canvas.js (requires jsGraphics)