Oct 09

Francois Laberge has a fun demonstration of creating 3d looking effects via lighting and normal mapping on 2d photos.

The demos progressively add features, from left to right lighting, to glow effects, to a multiple colored lighting extravaganza! Very nice work Francois!

Continue reading »

Tagged with:
Sep 10

Marco Lisci has written a tutorial on creating a black and white image effect using the Canvas tag.

The heart of his tutorial is using getImageData() and looping through the red, green, blue, and alpha values of each pixel to change it’s luminance:

So, what can we use to make an image black and white? The luminance. The luminance is how much a color is luminous to the human eye and it’s used to measure the clipping white in video editing systems, for example. In video editing system a white color that “break” the screen is a white that is too white to be represented on a common TV.

This is important because by calculating the average number between red, green and blue values we could obtain a value for every pixel that represent a static mathematical representation of the color luminance.

But there’s a problem, an human eye see colors dynamically. For example, if we take similar shades of blue and green, our eyes will detect the green color more luminous than the blue. In our algorithm we could use the static average formula, but our image will be too flat, and we’ll lose a lot of color depth.

So, let’s introduce the luminance formula: red x 0.3 + green x 0.59 + blue x 0.11.

This formula calculates the luminance of a color as it’s perceived by the human eye, so the green channel has more importance than the red and the blue. In our Javascript code we calculate for every pixel the grayscale number, by using exactly this formula. Then we assign this value to the red, green and blue channels of our pixel. By doing this for every pixel we are able to get a black and white version of our original image. There are obviously other more complex methods to calculate the correct grayscale value, but they could be too heavy to be used in an HTML5 canvas element, and we can say that for an everyday use, the luminance algorithm is good.

Resulting in code that looks as follows:

JAVASCRIPT:

var imgd = context.getImageData(0, 0, 500, 300);
var pix = imgd.data;
for (var i = 0, n = pix.length; i <n; i += 4) {
  var grayscale = pix[i] * .3 + pix[i+1] * .59 + pix[i+2] * .11;
  pix[i] = grayscale;       // red
  pix[i+1] = grayscale;  // green
  pix[i+2] = grayscale;  // blue
  // alpha
}
context.putImageData(imgd, 0, 0);
 

It would be cool to see this combined as a kind of filter that can be applied to do black and white roll-over effects of elements, similar to what you can do with SVG filters.

[via Mark Mildner]

Continue reading »

Tagged with:
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:
preload preload preload