Aug 30

Via Phil Franks comes an interesting HTML5/CSS3 site for There Studio, which is a kind of coworking space in London:

The site itself has a number of circles with information bouncing on the screen that respond to mouse clicks and moves.

Let’s crack the site open using View Source and see how they are doing things. First, they have a repeated background with a little plus symbol with the following style rule on the <body> tag:

CSS:

background: #ddd url(‘../images/bg.gif’) 50% 0 repeat fixed;
 

The textual content in each of the circles is clean semantic HTML that is search engine friendly:

HTML:

<div class=“section who first”>
  <h3>Who</h3>
  <p>Creatives, makers, thinkers <span class=“ampersand”>&amp;</span> doers</p>
</div>

To turn that into this:

The <h3> is first transformed into having an underline with the padding and margin being on the bottom:

CSS:

h3 {
        border-bottom: 1px solid #ccc;
        display: block;
        font-size: 25px;
        font-weight: normal;
        padding: 0 0 10px;
        margin: 0 0 8px;
}
 

JavaScript creates the circle. The script tags themselves are at the end of the HTML page at the bottom of the <body> tag, a good performance practice in general.

The heart of drawing each circle is in the createBall and createContentBall methods. If a ball will have HTML content, then the createContentBall method is used, otherwise the createBall method is used. Let’s look at the createContentBall method; we’ll break it down:

JAVASCRIPT:

function createContentBall(className,size,color,html) {
  var element = document.createElement( ‘div’ );
  element.className = className;
  element.width = element.height = size;
  element.style.position = ‘absolute’;
  element.style.left = -size + ‘px’;
  element.style.top = -size + ‘px’;
  element.style.cursor = “default”;
  canvas.appendChild(element);
  elements.push( element );
  var circle = document.createElement( ‘canvas’ );
  circle.width = size;
  circle.height = size;
  if (className !==‘image’ && className !==‘image first’) {
    var graphics = circle.getContext( ’2d’ );
    graphics.fillStyle = color;
    graphics.beginPath();
    graphics.arc( size * .5, size * .5, size * .5, 0, PI2, true );
    graphics.closePath();
    graphics.fill();
  }
  element.appendChild( circle );
  content = document.createElement( ‘div’ );
  content.className = “content”;
  content.onSelectStart = null;
  content.innerHTML = html;
  element.appendChild(content);
  if (className !==‘image’ && className !==‘image first’ ) {
    content.style.width = (size – contentPadding*2) + ‘px’;
    content.style.left = (((size – content.clientWidth) / 2)) +‘px’;
    content.style.top = ((size – content.clientHeight) / 2) +‘px’;
  }
  var b2body = new b2BodyDef();
  var circle = new b2CircleDef();
  circle.radius = size / 2;
  circle.density = ballDensity;
  circle.friction = ballFriction;
  circle.restitution = ballRestitution;
  b2body.AddShape(circle);
  b2body.userData = {element: element};
  b2body.position.Set( Math.random() * stage[2], Math.random() * (stage[3]-size) + size/2);
  b2body.linearVelocity.Set( Math.random() * 200, Math.random() * 200 );
  bodies.push( world.CreateBody(b2body) );
}
 

First, we create an absolutely positioned DIV that will house our Canvas tag:

JAVASCRIPT:

var element = document.createElement( ‘div’ );
element.className = className;
element.width = element.height = size;
element.style.position = ‘absolute’;
element.style.left = -size + ‘px’;
element.style.top = -size + ‘px’;
element.style.cursor = “default”;
canvas.appendChild(element);
elements.push( element );
 

Then we draw the actual circle itself using the Canvas tag and append it to our container DIV (Note that an SVG circle created programmatically could have also been used here):

JAVASCRIPT:

var circle = document.createElement( ‘canvas’ );
circle.width = size;
circle.height = size;
if (className !==‘image’ && className !==‘image first’) {
   var graphics = circle.getContext( ’2d’ );
   graphics.fillStyle = color;
   graphics.beginPath();
   graphics.arc( size * .5, size * .5, size * .5, 0, PI2, true );
   graphics.closePath();
   graphics.fill();
}
element.appendChild( circle );
 

Then we create another DIV to house the HTML content itself:

JAVASCRIPT:

content = document.createElement( ‘div’ );
content.className = “content”;
content.onSelectStart = null;
content.innerHTML = html;
element.appendChild(content);
if (className !==‘image’ && className !==‘image first’ ) {
   content.style.width = (size – contentPadding*2) + ‘px’;
   content.style.left = (((size – content.clientWidth) / 2)) +‘px’;
   content.style.top = ((size – content.clientHeight) / 2) +‘px’;
}
 

Notice that we are setting content.onSelectStart to null above; this is so that when you run the mouse button over the text it doesn’t select (An alternative way to do this is to use the HTML pointer-events CSS property).

Next comes code to deal with the physics of the circles, which uses Box2D.js, a JavaScript physics engine ported from Flash:

JAVASCRIPT:

var b2body = new b2BodyDef();
var circle = new b2CircleDef();
circle.radius = size / 2;
circle.density = ballDensity;
circle.friction = ballFriction;
circle.restitution = ballRestitution;
b2body.AddShape(circle);
b2body.userData = {element: element};
b2body.position.Set( Math.random() * stage[2], Math.random() * (stage[3]-size) + size/2);
b2body.linearVelocity.Set( Math.random() * 200, Math.random() * 200 );
bodies.push( world.CreateBody(b2body) );
 

Basically, we define a circle, give it a radius, density, friction, and restitution, and then add it to our collection of shapes with a position and linear velocity. Box2D will then handle the physics and we can just take the values back out to draw things on the screen with a setInterval, which happens in the loop method:

JAVASCRIPT:

function loop() {
  delta[0] += (0 – delta[0]) * .5;
  delta[1] += (0 – delta[1]) * .5;
  world.m_gravity.x = 0 // -(0 + delta[0]);
  world.m_gravity.y = -(100 + delta[1]);
  mouseDrag();
  world.Step(timeStep, iterations);
  for (i = 0; i <bodies.length; i++) {
    var body = bodies[i];
    var element = elements[i];
    element.style.left = (body.m_position0.x(element.width>> 1)) + ‘px’;
    element.style.top = (body.m_position0.y(element.height>> 1)) + ‘px’;
    if (ballRotation && element.tagName == ‘DIV’) {
      var rotationStyle = ‘rotate(‘ + (body.m_rotation0 * 57.2957795) + ‘deg)’;
      element.style.WebkitTransform = rotationStyle;
      element.style.MozTransform = rotationStyle;
      element.style.OTransform = rotationStyle;
    }
  }
}
 

This method gets called with a setInterval periodically. Basically, we apply a delta and a gravity at each time step; see if the mouse is being pressed down (with hooks for touch devices like the iPhone to see if a finger is being pressed down); tell the Box2D World about our gravity and delta and to make an iteration step; and finally use the computed physics values from Box2D to apply CSS3 rotation transforms on our parent DIV and move the element’s CSS top and left values around the screen.

Continue reading »

Tagged with:
Aug 25

From Hakim El Hattab (who has some very nifty HTML5 experiments up) comes some nice tips on using the Canvas tag:

Cross browser implementation

There are no real discrepancies between the canvas outputs of different browsers so long as the JavaScript code is written correctly (if not, browsers tend to try and fix things for you, often resulting in varying results).

Performance

When working with animation on canvas, performance can be a challenge since bitmap operations are very processing expensive, especially at high resolutions. One important optimization rule to follow is to reuse as many pixels as possible between frames. What I mean by that is the fewer pixels that need to be processed each frame, the faster your program will run. A good example of this is when erasing pixels with the clearRect(x,y,w,h)method, it is very beneficial to clear and redraw only the pixels that have changed and not, for instance, a full screen 1920×1280 sized canvas. Unlike the Flash Player’s redraw regions, this management of “dirty rectangles” needs to be done manually for canvas.

State stack & transformation

The canvas can be manipulated via transformations such as rotation and scaling, resulting in a change to the canvas co-ordinate system. This is where it’s important to know about the state stack for which two methods are available: “save” (pushes the current state to the stack) and “restore” (reverts to the previous state). This enables you to apply transformation to a drawing and then restore back to the previous state to make sure the next shape is not affected by any earlier transformation. The states also include properties such as the fill and stroke colors.

Compositing

A very powerful tool at hand when working with canvas is compositing modes which, amongst other things, allow for masking and layering. As an example, you can check out Bakemono, where composite modes are used to mask the eye and mouth. There’s a wide array of available composite modes and they are all set through the canvas context’s “globalCompositeOperation” property.

Anti-aliasing

To allow for sub-pixel drawings, all browser implementations of canvas employ anti-aliasing (although this does not seem to be a requirement in the HTML5 spec). Anti-aliasing can be important to keep in mind if you want to draw crisp lines and notice the result looks blurred. To work around this you will need to either round to integer values or offset by half a pixel depending on if you’re drawing fills or strokes.

Clearing the canvas

To clear the entire canvas of any existing pixels you would normally use the clearRect(x,y,w,h) function but there is another option available. Whenever the width/height of the canvas are set, even if they are set to the value they already have, the canvas is reset. This is good to know when working with a dynamically sized canvas as you will notice drawings disappearing.

[via Mr. Doob]

Cross browser implementation

There are no real discrepancies between the canvas outputs of different browsers so long as the JavaScript code is written correctly (if not, browsers tend to try and fix things for you, often resulting in varying results).

Performance

When working with animation on canvas, performance can be a challenge since bitmap operations are very processing expensive, especially at high resolutions. One important optimization rule to follow is to reuse as many pixels as possible between frames. What I mean by that is the fewer pixels that need to be processed each frame, the faster your program will run. A good example of this is when erasing pixels with the clearRect(x,y,w,h)method, it is very beneficial to clear and redraw only the pixels that have changed and not, for instance, a full screen 1920×1280 sized canvas. Unlike the Flash Player’s redraw regions, this management of “dirty rectangles” needs to be done manually for canvas.

State stack & transformation

The canvas can be manipulated via transformations such as rotation and scaling, resulting in a change to the canvas co-ordinate system. This is where it’s important to know about the state stack for which two methods are available: “save” (pushes the current state to the stack) and “restore” (reverts to the previous state). This enables you to apply transformation to a drawing and then restore back to the previous state to make sure the next shape is not affected by any earlier transformation. The states also include properties such as the fill and stroke colors.

Compositing

A very powerful tool at hand when working with canvas is compositing modes which, amongst other things, allow for masking and layering. As an example, you can check out Bakemono, where composite modes are used to mask the eye and mouth. There’s a wide array of available composite modes and they are all set through the canvas context’s “globalCompositeOperation” property.

Anti-aliasing

To allow for sub-pixel drawings, all browser implementations of canvas employ anti-aliasing (although this does not seem to be a requirement in the HTML5 spec). Anti-aliasing can be important to keep in mind if you want to draw crisp lines and notice the result looks blurred. To work around this you will need to either round to integer values or offset by half a pixel depending on if you’re drawing fills or strokes.

Clearing the canvas

To clear the entire canvas of any existing pixels you would normally use the clearRect(x,y,w,h) function but there is another option available. Whenever the width/height of the canvas are set, even if they are set to the value they already have, the canvas is reset. This is good to know when working with a dynamically sized canvas as you will notice drawings disappearing.

Continue reading »

Tagged with:
Aug 22

Jacob Seidelin of nihilogic fame (remember his Super Mario in JavaScript solution) is one of my unsung heroes of JavaScript. His solutions have that Dean Edwards “genius bordering on the bat-sh*t-crazy” touch that make you shake your head in disbelief when they come out but later on become very interesting.

One of his posts from 2008 entitled “Compression using Canvas and PNG-embedded data” had a good idea: if you want to compress JavaScript and CSS you could reverse engineer a packing algorithm in JavaScript or you could use a lossless packing system that is already in use and supported in browsers. In this case the packed format is PNG and the way to unpack it is by using the canvas API’s getImageData() method:

JAVASCRIPT:

var x = function(z, m, ix ) { // image, callback, chunk index
  var o = new Image();
  o.onload = function() {
    var s = “”,
        c = d.createElement(“canvas”),
        t = c.getContext(“2d”),
        w = o.width,
        h = o.height;
    c.width = c.style.width = w;
    c.height = c.style.height = h;
    t.drawImage(o, 0, 0);
    var b = t.getImageData( 0, 0, w, h ).data; //b : bucket of data
    for(var i= 0; i <b.length; i += 4) {
      if( b[i]> 0 )
        s += String.fromCharCode(b[i]);
    }
    m(s, ix);
  }
  o.src = z;
}

As there are quite some interesting competitions going on that need really small JavaScript solutions Alex Le took up Jacob’s work and wrapped it in a build script that concatenates, packs and converts to a PNG and unpacks it for the 10K competition with a JavaScript. In the process Alex also found some bug in Internet Explorer 9′s canvas implementation as it only reads the first 8192 bytes of a PNG and returns 0 for the others :(.

It is pretty amazing how efficient this way of packing is. What we need to test now is when and if it is worth while to have the unpacking done on the client. Imagine adding your JS and CSS to the end of an image and cropping it in CSS to have all the info you need in an app in a single HTTP request. Let the games begin.

Continue reading »

Tagged with:
Jul 28

Javascript author extraordinaire David Flanagan released Canto.js recently, a lightweight wrapper API for canvas, introduced here and documented at the top of the source code. Example:

JAVASCRIPT:

canto(“canvas_id”).moveTo(100,100).lineTo(200,200,100,200).closePath().stroke();
 

Notice three things:

  • canto() returns an abstraction of the canvas – a “Canto” object.
  • As with jQuery and similar libraries, there’s method chaining; each method called on a Canto also returns the Canto.
  • lineTo() has been extended to support multiple lines being drawn in a single call.

Instead of setting the ink properties and then painting it, you can do it all in one step:

JAVASCRIPT:

canto(“canvas_id”).moveTo(100,100).lineTo(200,200,100,200).closePath().stroke({lineWidth: 15, strokeStyle: “red”});
 

And plenty more syntactic sugar – check out the API in the source code comments. Sweet!

Thanks @pkeane.

Continue reading »

Tagged with:
Jul 26

Interest in Canvas, as well as mobile apps, has led to a renaissance of old-school 8-bit graphics. Joe Huckaby of Effect Games has been playing around with color cycling, leading to some stunning effects.

Anyone remember Color cycling from the 90s? This was a technology often used in 8-bit video games of the era, to achieve interesting visual effects by cycling (shifting) the color palette. Back then video cards could only render 256 colors at a time, so a palette of selected colors was used. But the programmer could change this palette at will, and all the onscreen colors would instantly change to match. It was fast, and took virtually no memory.

There’s a neat optimization going on here too: instead of clearing and redrawing the entire scene with each frame, he only updates the pixels that change:

In order to achieve fast frame rates in the browser, I had to get a little crazy in the engine implementation. Rendering a 640×480 indexed image on a 32-bit RGB canvas means walking through and drawing 307,200 pixels per frame, in JavaScript. That’s a very big array to traverse, and some browsers just couldn’t keep up. To overcome this, I pre-process the images when they are first loaded, and grab the pixels that reference colors which are animated (i.e. are part of cycling sets in the palette). Those pixel X/Y offsets are stored in a separate, smaller array, and thus only the pixels that change are refreshed onscreen. This optimization trick works so well, that the thing actually runs at a pretty decent speed on my iPhone 3GS and iPad!

Continue reading »

Tagged with:
Jun 02

Greg Murray has an early beta of a fun sample app: HTML5 Fish Tank. The app lets you build out your fishes, and then place them in the tank.

It puts the low level Canvas and CSS3 transitions/transforms to work.

E.g.

HTML:

<div id=“1275463173677″ class=“fish” style=“-webkit-transition-duration: 3369ms; -webkit-transform-origin-x: 508px; -webkit-transform-origin-y: 485px; -webkit-transform: rotateY(0deg) translate(508px, 485px); “><div style=“position: absolute; margin-top: 27px; margin-left: 70px; “><canvas width=“30″ height=“44″ style=“width: 30px; height: 66px; “></canvas></div><div style=“position: absolute; margin-top: 25px; margin-left: 2px; “><canvas width=“71″ height=“71″ style=“width: 71.5px; height: 71.5px; “></canvas></div><div style=“position: absolute; margin-top: 40px; margin-left: 19px; “><canvas width=“20″ height=“20″ style=“width: 20px; height: 20px; “></canvas></div><div style=“position: absolute; margin-top: 59px; margin-left: 4px; “><canvas width=“44″ height=“44″ style=“width: 44px; height: 44px; “></canvas></div><div style=“position: absolute; margin-top: 45px; margin-left: 40px; “><canvas width=“20″ height=“20″ style=“width: 20px; height: 20px; “></canvas></div><div style=“position: absolute; margin-top: 19px; margin-left: 26px; “><canvas width=“33″ height=“33″ style=“width: 33px; height: 33px; “></canvas></div><div style=“position: absolute; margin-top: 81px; margin-left: 40px; “><canvas width=“44″ height=“44″ style=“width: 44px; height: 44px; “></canvas></div></div>
 

The fish animation is driven by code like this:

JAVASCRIPT:

function goFish( target) {
        if ( !target.lastPoint) {
            target.lastPoint = target.currentPoint;
        }
        if ( target.timer ) {
            clearTimeout(  target.timer );
        }
        target.currentPoint = getRandomPoint();
        target.style.webkitTransitionDuration = target.currentPoint.d;
        target.style.webkitTransformOrigin = target.currentPoint .x + ” “ + target.currentPoint.y;
        var _scale = “”;
        if ( target.lastPoint.x> target.currentPoint.x ) {
            _scale = “rotateY(-180deg)”;
        } else {
             _scale = “rotateY(0deg)”;
        }
         target.style.webkitTransform =  _scale + ” translate(“ + target.currentPoint.x + “px, “ + target.currentPoint.y + “px)”;
        target.lastPoint = target.currentPoint;
        target.timer = setTimeout( function () {
            console.log( “saved the day” );
            goFish( target);
        }( target.currentPoint.d + 2000 ) );
}
 

A fun little way to start your day.

Continue reading »

Tagged with:
May 27

We have learned to touch the DOM as little as possible for performance sakes. Batch up changes, and do one call to innerHTML say. Talk over the evil boundary of the DOM as infrequently as possible.

Well, Selim Arsever has found a similar tip for Canvas that caused a ~40% performance improvement on some of his code. He had an example that did pixel twiddling, looking like:

JAVASCRIPT:

canvas = document.getElementById(“canvas”);
context = canvas.getContext(“2d”);
image = context.getImageData(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);

var pixels = SCREEN_WIDTH*SCREEN_HEIGHT;
while(–pixels){
   image.data[4*i+0] = r; // Red value
   image.data[4*i+1] = g; // Green value
   image.data[4*i+2] = b; // Blue value
   image.data[4*i+3] = a; // Alpha value
}
context.putImageData(image, 0, 0);
 

After listening to Stoyan talk perf, he wondered if there was an issue with the image.data access, and changed the code to:

JAVASCRIPT:

canvas = document.getElementById(“canvas”);
context = canvas.getContext(“2d”);
image = context.getImageData(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);

var pixels = SCREEN_WIDTH*SCREEN_HEIGHT;
var imageData = image.data; // here we detach the pixels array from DOM
while(–pixels){
   imageData[4*i+0] = r; // Red value
   imageData[4*i+1] = g; // Green value
   imageData[4*i+2] = b; // Blue value
   imageData[4*i+3] = a; // Alpha value
}
image.data = imageData; // And here we attache it back
context.putImageData(image, 0, 0);
 

He wrapped this all up in a benchmark that showed the perf diff. It actually really seemed to matter when using closures for namespaces:

Continue reading »

Tagged with:
May 03

There are a few graphing libraries out there. The latest that we have been shown is RGraph by Richard Heyes:

RGraph is a graphing/charting software component for websites. It uses HTML5 technologies (the new Canvas tag) which is already present in most modern web browsers to create and show graphs/charts. The graphs are created inside the web browser, removing the burden from the webserver (just as rendering HTML works) and so it can alleviate some of the burden from a web server.

It supports a wide variety of graph types – from Bar charts, Line charts and Pie charts to Scatter, Rose and Radar charts. In total there’s roughly 15 base chart types available with further variations possible too.

It has interactive features (for example zoom, tooltips and annotations) which can improve the usability of a website/web application. It’s very easy to work with and extend.

Continue reading »

Tagged with:
Apr 12

We have been reminded of MAX showing Flash CS5 generating basic HTML5 code (Canvas/JS).

That’s right. Adobe is a tools company. Although it helps to own the platform (hence keeping Flash alive and wanting it to win) as the competition to build the best tools is a given, that doesn’t mean that they can’t compete on other platforms. To be frank, it isn’t like the Web has a ton of amazing tools to compete against anyway in fact, so I fully hope that with the success of HTML5 in the coming years, we see great tools from Adobe to help us deliver experiences. Especially for creative designer types… Adobe really gets those chaps (and chapesses).

What tools would you like to see from Adobe? Maybe we can get them to dust off their SVG? ;)

Check out the launch of Creative Suite 5.

Continue reading »

Tagged with:
Mar 29

We love to recursively implement one technology on top of another. We have had Canvas support added to IE via VML, Flash, and Silverlight. We have had SVG implemented in Flash. Flash implemented in SVG.

The latest experiment is from Gabe Lerner and is CanVG. As you can guess, it renders SVG files via the <canvas> element. All in a few hundred lines of code!.

Check out the test playground to see it in action.

canvg

Continue reading »

Tagged with:
Mar 26

Jonas Wagner has a perfect Friday fun demo that normal mapping and phong shading in JavaScript using Canvas. Your mouse cursor becomes the light source that dynamically lights up a 3D object:

3dlighting

Jonas discusses how his code works:

The 3D effect is basically created using 2 textures. One contains the color of each pixel and the other the surface normal. The color image is rendered using only indirect lighting (ambient occlusion in that case). The direct light is then calculated in real time using phong shading without the diffuse part. For a more accurate description, read the source. ;)

Continue reading »

Tagged with:
Mar 25

Given the current status of Canvas and the impending release of Apple’s iPad (which will have no Flash support at all), I finally decided to bite the bullet and do a complete rewrite of the Network Graph in JavaScript and Canvas.

This is Tom Preston-Werner of GitHub, from his recent posted about migrating the network graph functionality from Flash to Canvas.

githubnetworkgraph

This isn’t the first site to move over functionality, but Tom has a really interesting perspective on why he did this, what he likes about canvas, and what he wishes it had:

Where Canvas/JavaScript is better than Flash

  • Fewer lines of code and smaller deliverable size: Smaller code base and the compiled SWF file clocks in at 111k compared to the minified Canvas version at just 25k!
  • Flash works badly on Linux (and friends)
  • Inspectable/debuggable via browser
  • No compilation step
  • Better cursor handling
  • No need to focus to receive keyboard events

Where Canvas/JavaScript is worse than Flash

  • Have to handle clipping and redraw manually (SVG does better here too)
  • No embedded font support
  • No built-in multiline text wrap (painful for Bespin! ;)
  • No HTML fragment rendering. Yes! drawElement, drawElement, drawElement. Please user agents!

Continue reading »

Tagged with:
preload preload preload