Newer posts are loading.
You are at the newest post.
Click here to check if anything new just came in.

January 30 2014

07:30

Perfect Match: Adaptive Backgrounds for jQuery Colors Your Website Automagically


  

This plugin for jQuery is gas. Adaptive Backgrounds by Brian Gonzalez analyzes the colors of the images in your website, determines which ones are dominant and colors the background of the element containing the image accordingly. As Adaptive Backgrounds works with the nearest parent by default, you can have multiple different backgrounds on the same page. The effect is impressive.

January 22 2014

18:03

SVG and JavaScript: What Is Possible, What To Consider?


  

SVG has been around for quite some time now, waiting. Waiting for proper browser support. The wait is now over as all modern browsers support the format today. With Flash being on the decline, SVG has grown even more popular. Just like the proprietary Flash format, SVG is vector-based and can even contain animations. You need not even miss out on scripting, as SVG supports JavaScript right inside its own format. Think of an open ActionScript, only more commonly known.

Sponsored post
soup-sponsored
04:52

July 19 2012

18:50

WebGL Essentials: Part I

WebGL is an in-browser 3D renderer based on OpenGL, which lets you display your 3D content directly into an HTML5 page. In this tutorial I will cover all the essentials you need to get started using this framework.


Introduction

There are a couple things you should know before we get started. WebGL is a JavaScript API that renders 3D content to an HTML5 canvas. It does this by using two scripts that are known in the "3D world" as Shaders. The two shaders are:

  • The vertex shader
  • The fragment shader

Now don’t get too nervous when you hear these names; it’s just a fancy way of saying, "position calculator" and "color chooser" respectively. The fragment shader is the easier one to understand; it simply tells WebGL what color a given point on your model should be. The vertex shader is a little more technical, but basically it converts the points in your 3D models into 2D coordinates. Because all computer monitors are flat 2D surfaces, and when you see 3D objects on your screen, they are merely an illusion of perspective.

If you want to know exactly how this calculation works, you’d need to ask a mathematician, because it uses advanced 4 x 4 matrix multiplications, which are a bit beyond the ‘Essentials’ tutorial. Luckily, you don’t have to know how it works because WebGL will take care of most of it. So let’s get started.


Step 1: Setting Up WebGL

WebGL has a lot of small settings that you have to setup nearly every time you draw something to the screen. In order to save time and make your code neat, I am going to make a JavaScript object that will contain all the ‘behind the scene’ things in a separate file. To get started, create a new file called ‘WebGL.js’ and place the following code inside it:

function WebGL(CID, FSID, VSID){
	var canvas = document.getElementById(CID);
	if(!canvas.getContext("webgl") && !canvas.getContext("experimental-webgl"))
		alert("Your Browser Doesn't Support WebGL");
	else
	{
		this.GL = (canvas.getContext("webgl")) ? canvas.getContext("webgl") : canvas.getContext("experimental-webgl");	
		
		this.GL.clearColor(1.0, 1.0, 1.0, 1.0); // this is the color 
		this.GL.enable(this.GL.DEPTH_TEST); //Enable Depth Testing
		this.GL.depthFunc(this.GL.LEQUAL); //Set Perspective View
		this.AspectRatio = canvas.width / canvas.height;
		
		//Load Shaders Here
	}
}

This constructor function takes in the IDs of the canvas and the two shader objects. First, we get the canvas element and make sure it supports WebGL. If it does, then we assign the WebGL context to a local variable called "GL". The clear color is simply the background color, and it is worth noting that in WebGL most of the parameters go from 0.0 to 1.0 so you would have to divide your rgb values by 255. So in our example 1.0, 1.0, 1.0, 1.0 means a white background with 100% visibility (no transparency). The next two lines tell WebGL to calculate depth and perspective so that an object closer to you will block objects behind it. Finally, we set the aspect ratio which is calculated by dividing the canvas’s width by it’s height.

Before we continue and load the two shaders, let’s write them. I am going to write these in the HTML file where we are going to put the actual canvas element. Create an HTML file, and place the following two script elements just before the closing body tag:

<script id="VertexShader" type="x-shader/x-vertex">
  
	attribute highp vec3 VertexPosition;
	attribute highp vec2 TextureCoord;
	
	
	uniform highp mat4 TransformationMatrix;
	uniform highp mat4 PerspectiveMatrix;
	
	varying highp vec2 vTextureCoord;
	
	void main(void) {
		gl_Position = PerspectiveMatrix * TransformationMatrix * vec4(VertexPosition, 1.0);
		vTextureCoord = TextureCoord;
	}
</script>

<script id="FragmentShader" type="x-shader/x-fragment"> 
	varying highp vec2 vTextureCoord;
	
	uniform sampler2D uSampler;
	
	void main(void) {
		highp vec4 texelColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
		gl_FragColor = texelColor;
	}     
</script>

The vertex shader is created first, and we define two attributes:

  • the vertex position, which is the location in x,y and z coordinates of the current vertex (Point in your Model)
  • the texture coordinate; the location in the texture image that should be assigned to this point

Next, we create variables for the transformation and perspective matrices. These are used to convert the 3D model into a 2D image. The next line creates a shared variable to the fragment shader, and in the main function we calculate the gl_Position (the final 2D position). We then assign the ‘current texture coordinate’ to the shared variable.

In the fragment shader we just take the coordinates we defined in the vertex shader and we ‘sample’ the texture at that coordinate. Basically we are just getting the color in the texture that corresponds to the current point on our geometry.

Now that we have written the shaders, we can go back to loading them in our JS file. So replace the "//Load Shaders Here" with the following code:

var FShader = document.getElementById(FSID);
var VShader = document.getElementById(VSID);

if(!FShader || !VShader)
	alert("Error, Could Not Find Shaders");
else
{
	//Load and Compile Fragment Shader
	var Code = LoadShader(FShader);
	FShader = this.GL.createShader(this.GL.FRAGMENT_SHADER);
	this.GL.shaderSource(FShader, Code);
	this.GL.compileShader(FShader);
	
	//Load and Compile Vertex Shader
	Code = LoadShader(VShader);
	VShader = this.GL.createShader(this.GL.VERTEX_SHADER);
	this.GL.shaderSource(VShader, Code);
	this.GL.compileShader(VShader);
	
	//Create The Shader Program
	this.ShaderProgram = this.GL.createProgram();
	this.GL.attachShader(this.ShaderProgram, FShader);
	this.GL.attachShader(this.ShaderProgram, VShader);
	this.GL.linkProgram(this.ShaderProgram);
	this.GL.useProgram(this.ShaderProgram);
	
	//Link Vertex Position Attribute from Shader
	this.VertexPosition = this.GL.getAttribLocation(this.ShaderProgram, "VertexPosition");
	this.GL.enableVertexAttribArray(this.VertexPosition);
	
	//Link Texture Coordinate Attribute from Shader
	this.VertexTexture = this.GL.getAttribLocation(this.ShaderProgram, "TextureCoord");
	this.GL.enableVertexAttribArray(this.VertexTexture);
}

Your textures have to be in even byte sizes or you will get an error…like 2×2, 4×4, 16×16, 32×32…

We first make sure that the shaders exist, and then we move on to loading them one at a time. The process basically gets the shader’s source code, compiles it, and attaches it to the central shader program. There is a function, called LoadShader, that gets the shader code from the HTML file; we will get to that in a second. We use the ‘shader program’ to link the two shaders together, and it give us access to their variables. We store the two attributes we defined in the shaders; so we can input our geometry into them later.

Now let’s look at the LoadShader function, You should put this outside of the WebGL function:

function LoadShader(Script){
	var Code = "";
	var CurrentChild = Script.firstChild;
	while(CurrentChild)
	{
		if(CurrentChild.nodeType == CurrentChild.TEXT_NODE)
			Code += CurrentChild.textContent;
		CurrentChild = CurrentChild.nextSibling;
	}
	return Code;
}

It basically just cycles through the shader and collects the source code.


Step 2: The "Simple" Cube

In order to draw objects in WebGL you are going to need the following three arrays:

  • vertices; the points that make up your objects
  • triangles; tells WebGL how to connect the vertices into surfaces
  • texture coordinates; defines how the vertices are mapped on the texture image

This is referred to as UV mapping. For our example let’s create a basic cube. I will split the cube into 4 vertices per side which connect into two triangles. let’s make a variable that will hold a cube’s arrays.

var Cube = {
	Vertices : [ // X, Y, Z Coordinates
	
		//Front
		
		 1.0,  1.0,  -1.0,
		 1.0, -1.0,  -1.0,
		-1.0,  1.0,  -1.0,
		-1.0, -1.0,  -1.0,
		
		//Back
		
		 1.0,  1.0,  1.0,
		 1.0, -1.0,  1.0,
		-1.0,  1.0,  1.0,
		-1.0, -1.0,  1.0,
		
		//Right
		
		 1.0,  1.0,  1.0,
		 1.0, -1.0,  1.0,
		 1.0,  1.0, -1.0,
		 1.0, -1.0, -1.0,
		 
		 //Left
		 
		-1.0,  1.0,  1.0,
		-1.0, -1.0,  1.0,
		-1.0,  1.0, -1.0,
		-1.0, -1.0, -1.0,
		
		//Top
		
		 1.0,  1.0,  1.0,
		-1.0, -1.0,  1.0,
		 1.0, -1.0, -1.0,
		-1.0, -1.0, -1.0,
		
		//Bottom
		
		 1.0, -1.0,  1.0,
		-1.0, -1.0,  1.0,
		 1.0, -1.0, -1.0,
		-1.0, -1.0, -1.0
	
	],
	Triangles : [ // Also in groups of threes to define the three points of each triangle
		//The numbers here are the index numbers in the vertex array
		
		//Front
		
		0, 1, 2,
		1, 2, 3,
		
		//Back
		
		4, 5, 6,
		5, 6, 7,
		
		//Right
		
		8, 9, 10,
		9, 10, 11,
		
		//Left
		
		12, 13, 14,
		13, 14, 15,
		
		//Top
		
		16, 17, 18,
		17, 18, 19,
		
		//Bottom
		
		20, 21, 22,
		21, 22, 23
		
	],
	Texture : [ //This array is in groups of two, the x and y coordinates (a.k.a U,V) in the texture
		//The numbers go from 0.0 to 1.0, One pair for each vertex
		
		 //Front
		 
		 1.0, 1.0,
		 1.0, 0.0,
		 0.0, 1.0,
		 0.0, 0.0,
		 
		
		 //Back
		
		 0.0, 1.0,
		 0.0, 0.0,
		 1.0, 1.0,
		 1.0, 0.0,
		
		 //Right
		
		 1.0, 1.0,
		 1.0, 0.0,
		 0.0, 1.0,
		 0.0, 0.0,
		 
		 //Left
		 
		 0.0, 1.0,
		 0.0, 0.0,
		 1.0, 1.0,
		 1.0, 0.0,
		
		 //Top
		
		 1.0, 0.0,
		 1.0, 1.0,
		 0.0, 0.0,
		 0.0, 1.0,
		
		 //Bottom
		
		 0.0, 0.0,
		 0.0, 1.0,
		 1.0, 0.0,
		 1.0, 1.0
	]
};

It may seem like a lot of data for a simple cube, however, in in part two of this tutorial, I will make a script that will import your 3D models so you don’t have to worry about calculating these.

You may also be wondering why I made 24 points (4 for each side), when there is really only eight total unique points on a cube? I did this because you can only assign one texture coordinate per vertex; so if we would only put in the 8 points, then the whole cube would have to look the same because it would wrap the texture around all the sides that the vertex touches. But this way, each side has it’s own points so we can put a different part of the texture on each side.

We now have this cube variable and are ready to start drawing it. Let’s go back to the WebGL method and add a Draw function.


Step 3: The Draw Function

The procedure for drawing objects in WebGL has a lot of steps; so, it’s a good idea to make a function to simplify the process. The basic idea is to load the three arrays into WebGL buffers. We then connect these buffers to the attributes we defined in the shaders along with the transformation and perspective matrices. Next, we have to load the texture into memory, and, finally, we can call the draw command. So let’s get started.

The following code goes inside the WebGL function:

this.Draw = function(Object, Texture)
{
    var VertexBuffer = this.GL.createBuffer(); //Create a New Buffer

    //Bind it as The Current Buffer
    this.GL.bindBuffer(this.GL.ARRAY_BUFFER, VertexBuffer);

    // Fill it With the Data
    this.GL.bufferData(this.GL.ARRAY_BUFFER, new Float32Array(Object.Vertices), this.GL.STATIC_DRAW);

    //Connect Buffer To Shader's attribute
    this.GL.vertexAttribPointer(this.VertexPosition, 3, this.GL.FLOAT, false, 0, 0);

    //Repeat For The next Two
    var TextureBuffer = this.GL.createBuffer();
    this.GL.bindBuffer(this.GL.ARRAY_BUFFER, TextureBuffer);
    this.GL.bufferData(this.GL.ARRAY_BUFFER, new Float32Array(Object.Texture), this.GL.STATIC_DRAW);
    this.GL.vertexAttribPointer(this.VertexTexture, 2, this.GL.FLOAT, false, 0, 0);
    var TriangleBuffer = this.GL.createBuffer();
    this.GL.bindBuffer(this.GL.ELEMENT_ARRAY_BUFFER, TriangleBuffer);
    //Generate The Perspective Matrix
    var PerspectiveMatrix = MakePerspective(45, this.AspectRatio, 1, 10000.0);

    var TransformMatrix = MakeTransform(Object);

    //Set slot 0 as the active Texture
    this.GL.activeTexture(this.GL.TEXTURE0);

    //Load in the Texture To Memory
    this.GL.bindTexture(this.GL.TEXTURE_2D, Texture);

    //Update The Texture Sampler in the fragment shader to use slot 0
    this.GL.uniform1i(this.GL.getUniformLocation(this.ShaderProgram, "uSampler"), 0);

    //Set The Perspective and Transformation Matrices
    var pmatrix = this.GL.getUniformLocation(this.ShaderProgram, "PerspectiveMatrix");
    this.GL.uniformMatrix4fv(pmatrix, false, new Float32Array(PerspectiveMatrix));

    var tmatrix = this.GL.getUniformLocation(this.ShaderProgram, "TransformationMatrix");
    this.GL.uniformMatrix4fv(tmatrix, false, new Float32Array(TransformMatrix));

    //Draw The Triangles
    this.GL.drawElements(this.GL.TRIANGLES, Object.Trinagles.length, this.GL.UNSIGNED_SHORT, 0);
};

The vertex shader positions, rotates, and scales your object based on the transformation and perspective matrices. We will go more in depth into transformations in the second part of this series.

I have added two functions: MakePerspective() and MakeTransform(). These just generate the necessary 4×4 Matrices for WebGL. The MakePerspective() function accepts the vertical field of view, the aspect ratio, and the nearest and farthest points as arguments. Anything that is closer than 1 unit and farther than 10000 units will not be displayed, but you can edit these values to get the effect you are looking for. Now let’s take a look at these two functions:

function MakePerspective(FOV, AspectRatio, Closest, Farest){
	var YLimit = Closest * Math.tan(FOV * Math.PI / 360);
	var A = -( Farest + Closest ) / ( Farest - Closest );
	var B = -2 * Farest * Closest / ( Farest - Closest );
	var C = (2 * Closest) / ( (YLimit * AspectRatio) * 2 );
	var D =	(2 * Closest) / ( YLimit * 2 );
	return [
		C, 0, 0, 0,
		0, D, 0, 0,
		0, 0, A, -1,
		0, 0, B, 0
	];
}
function MakeTransform(Object){
	return [
		1, 0, 0, 0,
		0, 1, 0, 0,
		0, 0, 1, 0,
		0, 0, -6, 1
	];
}

Both these matrices effect the final look of your objects, but the perspective matrix edits your ’3D world’ like the field of view and the visible objects while the transformation matrix edits the individual objects like their rotation scale and position. With this done we are almost ready to draw, all that’s left is a function to convert an image into a WebGL texture.


Step 4: Loading Textures

Loading a texture is a two step process. First we have to load an image like you would in a standard JavaScript application, and then we have to convert it to a WebGL texture. So let’s start with the second part since we are already in the JS file. Add the following at the bottom of the WebGL function right after the Draw command:

this.LoadTexture = function(Img){
	//Create a new Texture and Assign it as the active one
	var TempTex = this.GL.createTexture();
	this.GL.bindTexture(this.GL.TEXTURE_2D, TempTex);  
	
	//Flip Positive Y (Optional)
	this.GL.pixelStorei(this.GL.UNPACK_FLIP_Y_WEBGL, true);
	
	//Load in The Image
	this.GL.texImage2D(this.GL.TEXTURE_2D, 0, this.GL.RGBA, this.GL.RGBA, this.GL.UNSIGNED_BYTE, Img);  
	
	//Setup Scaling properties
	this.GL.texParameteri(this.GL.TEXTURE_2D, this.GL.TEXTURE_MAG_FILTER, this.GL.LINEAR);  
	this.GL.texParameteri(this.GL.TEXTURE_2D, this.GL.TEXTURE_MIN_FILTER, this.GL.LINEAR_MIPMAP_NEAREST);  
	this.GL.generateMipmap(this.GL.TEXTURE_2D); 
	
	//Unbind the texture and return it.
	this.GL.bindTexture(this.GL.TEXTURE_2D, null);
	return TempTex;
};

It’s worth noting that your textures have to be in even byte sizes, or you will receive an error; so they have to be dimensions, like 2×2, 4×4, 16×16, 32×32, and so on. I added the line to flip the Y coordinates simply because my 3D application’s Y coordinates were backward, but it will depend on what you are using. This is due to some programs making 0 in the Y axis the top left corner and some applications make it the bottom left corner. The scaling properties that I set just tell WebGL how the image should up-scale and down-scale. You can play around with different options to get different effects, but I thought these worked best.

Now that we are done with the JS file, let’s return to the HTML file and implement all of this.


Step 5: Wrapping It Up

As I mentioned earlier, WebGL renders to a canvas element. That’s all we need in the body section. After adding the canvas element, your html page should look like the following:

<html>
	<head>
		<!-- Include Our WebGL JS file -->
		<script src="WebGL.js" type="text/javascript"></script>
		<script>
			
		</script>
	</head>
	<body onload="Ready()">  
	  <canvas id="GLCanvas" width="720" height="480">
	    	Your Browser Doesn't Support HTML5's Canvas.  
	  </canvas>
	  
	<!-- Your Vertex Shader -->
	
	<!-- Your Fragment Shader -->
	
	</body>
</html>

It’s a pretty simple page. In the head area I have linked to our JS file. Now let’s go implement our Ready function, which gets called when the page loads:

//This will hold our WebGL variable
var GL; 
	
//Our finished texture
var Texture;
	
//This will hold the textures image 
var TextureImage;
	
function Ready(){
	GL = new WebGL("GLCanvas", "FragmentShader", "VertexShader");
	TextureImage = new Image();
	TextureImage.onload = function(){
		Texture = GL.LoadTexture(TextureImage);
		GL.Draw(Cube, Texture);
	};
	TextureImage.src = "Texture.png";
}

So we create a new WebGL object and pass in the IDs for the canvas and shaders. Next, we load the texture image. Once loaded, we call the Draw() method with the Cube and the Texture. If you followed along, your screen should have a static cube with a texture on it.

Now even though I said we will cover transformations next time, I can’t just leave you with a static square; it’s not 3D enough. Let’s go back and add a small rotation. In the HTML file, change the onload function to look like so:

TextureImage.onload = function(){
		Texture = GL.LoadTexture(TextureImage);
		setInterval(Update, 33);
};

This will call a function called Update() every 33 milliseconds which will give us a frame rate of about 30 fps. Here is the update function:

function Update(){
	GL.GL.clear(16384 | 256);
	GL.Draw(GL.Cube, Texture);
}

This is a fairly simple function; it clears the screen and then draws the updated Cube. Now, let’s go to the JS file to add the rotation code.


Step 6: Adding Some Spin

I’m not going to fully implement transformations, because I’m saving that for next time, but let’s add a rotation around the Y-axis. The first thing to do is add a Rotation variable to our Cube object. This will keep track of the current angle, and allow us to keep incrementing the rotation. So the top of your Cube variable should look like this:

var Cube = {
	Rotation : 0,
	//The Other Three Arrays
};

Now let’s update the MakeTransform() function to incorporate the rotation:

function MakeTransform(Object){
	var y = Object.Rotation * (Math.PI / 180.0);
	var A = Math.cos(y);
	var B = -1 * Math.sin(y);
	var C = Math.sin(y);
	var D = Math.cos(y);
	Object.Rotation += .3;	
	return [
		A, 0, B, 0,
		0, 1, 0, 0,
		C, 0, D, 0,
		0, 0, -6, 1
	];
}

Conclusion

And that’s it! In the next tutorial, we will cover loading models and performing transformations. I hope you enjoyed this tutorial; feel free to leave any questions or comments that you might have below.


June 21 2011

13:30

How to Transition an Image from B&W to Color with Canvas

Advertise here

Recently, in the CodeCanyon forums, a question was brought up: “How do I transition an image from black and white, to color — using only one image?” Unfortunately, at this point in time, it’s not possible with CSS. However, if we’re creative with JavaScript and canvas, we can create a solution relatively easily. I’ll show you how in today’s video tutorial!

Choose 720p for maximum clarity.
Subscribe to our YouTube and Blip.tv channels to watch more screencasts.

Final Source

<!DOCTYPE html> 

<html lang="en">
<head>
   <meta charset="utf-8">
   <title>untitled</title>
	<style>
		/* Setup...not important. */
		.img-wrap {
			width: 500px;
			margin: 100px auto;
			position: relative;
			cursor: pointer;
		}

		/* Handles animation of b*w to color */
		canvas {
			position: absolute;
			left: 0;
			top: 0;
			opacity: 1;
			-webkit-transition: all 1s;
			-moz-transition: all 1s;
			-o-transition: all 1s;
			-ms-transition: all 1s;
			transition: all 1s;
		}

		canvas:hover {
			opacity: 0;
		}

		/* If you MUST have IE support */
		#cvs-src {
		   filter: progid:DXImageTransform.Microsoft.BasicImage(grayscale=1);
		}

		#cvs-src:hover {
			filter: none;
		}
	</style>
</head>
<body> 

<div class="img-wrap">
	<img id="cvs-src" src="your-image.jpg" />
	<canvas width=500 height=500></canvas>
</div> 

<script>
	(function() {
		var supportsCanvas = !!document.createElement('canvas').getContext;
		supportsCanvas && (window.onload = greyImages);

		function greyImages() {
			var ctx = document.getElementsByTagName("canvas")[0].getContext('2d'),
				img = document.getElementById("cvs-src"),
				imageData, px, length, i = 0,
				grey;

			ctx.drawImage(img, 0, 0);

			// Set 500,500 to the width and height of your image.
			imageData = ctx.getImageData(0, 0, 500, 500);
			px = imageData.data;
			length = px.length;

			for ( ; i < length; i+= 4 ) {
				grey = px[i] * .3 + px[i+1] * .59 + px[i+2] * .11;
				px[i] = px[i+1] = px[i+2] = grey;
			}

			ctx.putImageData(imageData, 0, 0);
		}
	})();
</script> 

</body>
</html>

Conclusion

So what do you think? Would you use this technique in your own projects? Can you think of a better way that doesn’t involve using a server-side language or sprites? Let me know in the comments!

June 17 2011

21:41

Canvas from Scratch: Pixel Manipulation

Advertise here

In the last article, you learned all about transformations, shadows and gradients. Today, I’m going to show you how to manipulate pixels in canvas; from simply accessing color values, to editing images within the canvas just like a photo editor.

This is easily one of the most powerful features built into canvas directly, and once you’ve learned it, I guarantee that you’ll have a whole range of exciting ideas.


Setting Up

You’re going to use the same HTML template from the previous articles, so open up your favorite editor and copy in the following code:

<!DOCTYPE html>

<html>
    <head>
        <title>Canvas from scratch</title>
        <meta charset="utf-8">

        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>

        <script>
            $(document).ready(function() {
                var canvas = document.getElementById("myCanvas");
                var ctx = canvas.getContext("2d");
            });
        </script>
    </head>

    <body>
        <canvas id="myCanvas" width="500" height="500">
            <!-- Insert fallback content here -->
        </canvas>
    </body>
</html>

This is nothing more than a basic HTML page with a canvas element and some JavaScript that runs after the DOM has loaded. Nothing crazy.


Placing an Image on the Canvas

You can manipulate pixels with anything drawn onto the canvas, but for the sake of this tutorial, you’ll be using images. This is partly because it’s important to show you how to load images into the canvas, but also because the ability to perform image manipulation (eg. editing photos) is massive plus-point of this technology.

Before I show you how to access pixel values, let’s place an image onto the canvas. Feel free to use any image that you want, but for the sake of this example, I’m going to use one of my own photos from Flickr.

One of my photos from Flickr

You have permission to use this photo if you wish, which you can download in a variety of sizes.

Loading an image into canvas requires two steps. The first is to load the image into a HTML image element, which can be done using HTML or by creating a new DOM element directly within JavaScript. In this example, you’re going to create a new DOM element — it’s dead simple:

var image = new Image();
image.src = "sample.jpg";
$(image).load(function() {

});

All you’re doing here is creating a new Image DOM element and assigning it to a variable. You then use that variable to load up your image by setting the src attribute of the image to the correct path. It’s worth noting that you could load in a remote image using this technique, but this raises a few issues for us further down the line so we’ll stick with a locally stored image for now. The final step is to listen for the load event that will be fired as soon as the image has finished loading and is available for use.

Once the image has loaded, you can then place it on the canvas in one easy step. All you need to do is pass the image variable that you just created into a call to the drawImage method of the 2d rendering context. Place it inside the image load event, like so:

$(image).load(function() {
    ctx.drawImage(image, 0, 0);
});

In this case, the drawImage method takes three arguments; an image element, as well as the x and y coordinate values to place the image on the canvas. This will draw the image at full size (500px for this image) and at the specified position:

Placing an image

However, drawImage can actually take a further two arguments that define the width and height to draw the image, like so:

ctx.drawImage(image, 0, 0, 250, 166);

This would draw the image at half the original size (250px for this image):

Placing and resizing an image

You can even take things a step further and use the full nine arguments for drawImage to only draw a small portion of the original image, like so:

ctx.drawImage(image, 0, 0, 200, 200, 0, 0, 500, 500);

This would take a 200px square from the top left of the image and draw it on the canvas at 500px square:

Placing only part of an image

In pseudo-code, the full nine drawImage arguments can be described like so (s meaning source, and d meaning destination):

ctx.drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh);

And the result is visualized in the following illustration:

Taking drawImage to the extreme

Simple, right? In all honesty, nothing in canvas is that complicated once you break it down and look at the pieces individually.


Accessing Pixel Values

Now that you have an image on the canvas it’s time to access the pixels so that you can manipulate them. However, let’s forget about manipulating them for now and concentrate purely on accessing them as the concept take a little while to get your head around.

Security Issues

If you want to access pixels using canvas you need to be aware of the security limitations that are involved. These limitations only allow you to access the data from images loaded on the same domain as the JavaScript. This prevents you from accessing an image from a remote server and then analyzing its pixels, although there is a way to get around it, sort of. Unfortunately not all browsers treat JavaScript and images run locally from the file system (ie, without a domain name) as under the same domain, so you might receive security errors. To get around this you need to either run the rest of this tutorial on a local development environment (like MAMP, WAMP, or XAMPP) or a remote Web server and access the files using a domain name (like example.com).

With that out of the way, let’s crack on and get us some pixels!

Accessing Pixels is a Little Odd

As I mentioned at the beginning of this section, accessing pixel values in canvas takes a little while to get your head around. This is due to the way that the pixels are stored by canvas; they’re not stored as whole pixels at all! Instead, pixels are each broken up into four separate values (red, green, blue, and alpha) and these values are stored in a one-dimensional array with all the color values for the other pixels. Because of this you can’t just request the data from a particular pixel, at least not by default. Let me explain.

To access pixels in canvas you need to call the getImageData method of the 2d rendering context, like so:

var imageData = ctx.getImageData(x, y, width, height);

This method takes four arguments that describe a rectangular area of the canvas that you want the pixel data from; an x and y origin, followed by a width and height. It returns a CanvasPixelArray that contains all the color values for the pixels within the defined area. The first thing to notice with the CanvasPixelArray is that each pixel has four color values, so the index of the first color value for each pixel within the array will be a multiple of 4 (0 for the first value of the first pixel, 4 for the first value of the second, etc):

Index values in the CanvasPixelArray

What’s interesting about this array (or annoying, depending on how you look at it) is that there is no concept of (x, y) coordinate position, meaning that retrieving color values for a specific pixel is a little harder than accessing a two-dimensional array (eg. using pixelArray[0][3] to access the pixel at (1, 4)). Instead, you need to use a little formula that’s actually very easy to understand once it’s explained properly:

var redValueForPixel = ((y - 1) * (width * 4)) + ((x - 1) * 4);
Accessing a specific pixel from the CanvasPixelArray

Can you work out what’s happening here? Let’s break it down and pretend that we want to get the pixel color values for the innermost pixel in a 3×3 pixel grid – the pixel at (2, 2).

If you look at the previous two images you can see that the color values for this pixel will begin at index 16, but to work this out with code you need to do two things; first calculate the index at the beginning of the row that the pixel is on (the y position), and then add to that index the number of color values that exist between the pixel and the beginning of the row (the x position). It’s a bit of a mind-bender, but bear with it.

The first part is easy, you already know that there are four color values per pixel, and you already know the width of the grid (3 pixels). To calculate the index of the pixel at row y (2) you pass these values through the first part of the formula, which would look like so:

((2 - 1) * (3 * 4))

This gives you an index of 12, which you’ll see matches up with the first pixel on the second row in the previous images. So far so good.

The next step is to calculate the number of color values that exist before the pixel that you want on this row. To do that you simply multiply the number of pixels before the one you want by four. Simple. In this case the second part of the formula would look like this:

((2 - 1) * 4)

You can work it all out if you want, but the answer is 4, which when added to the previous value gives you an index of 16. Cool, ey?

I wouldn’t worry too much about understanding it fully, just know that this amazing little formula exists so that you can easily get the index of the red color value for any pixel. To get the index of the other color values of a pixel (green, blue, or alpha), you just add 1, 2, or 3 to the calculated index respectively.

Putting this into Practice

Now that you know how to grab any pixel that you want, let’s put this into practice and grab color values from an image to change the color of a website background. This kind of technique would work great as a color picker for a photo editing Web application.

The code for this example is fairly straightforward, so let’s attack it all in one go:

var image = new Image();
image.src = "sample.jpg";
$(image).load(function() {
    ctx.drawImage(image, 0, 0);
});

$(canvas).click(function(e) {
    var canvasOffset = $(canvas).offset();
    var canvasX = Math.floor(e.pageX-canvasOffset.left);
    var canvasY = Math.floor(e.pageY-canvasOffset.top);

    var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    var pixels = imageData.data;
    var pixelRedIndex = ((canvasY - 1) * (imageData.width * 4)) + ((canvasX - 1) * 4);
    var pixelcolor = "rgba("+pixels[pixelRedIndex]+", "+pixels[pixelRedIndex+1]+", "+pixels[pixelRedIndex+2]+", "+pixels[pixelRedIndex+3]+")";

    $("body").css("backgroundColor", pixelcolor);
});

You’ll recognise the first few lines from the previous examples. All the new stuff is within the click handler on the canvas element, which uses a tiny bit of jQuery to tell you when the canvas has been clicked on.

Within the click handler you want to work out the pixel that the mouse has clicked on the canvas. To do this you first need to calculate the offset in pixels of the top left position of the canvas from the top left edge of the browser window, you can use the jQuery offset method for this. You can then infer the pixel clicked on the canvas by subtracting the offset from the mouse position of the click event (pageX and pageY). You should definitely spend some time reading up on the JavaScript click event if you want to understand this further.

The following four lines grab the CanvasPixelArray for the canvas (getImageData), store it in a variable, find the index of the red color value for the clicked pixel by calculating it using the formula that you saw earlier, and then stores the pixel color values as a CSS rgba string. Finally, the last step is to set the background color of the body element to that of the clicked pixel.

Creating a basic color picker

And with that you’re done. Try it out for yourself; click the image on the canvas and watch the background of the website change color. If it doesn’t work, make sure that you’re running the demo on a server with a domain name, like described in the section on security issues.

It’s been a long journey, but you’re now able to quickly and easily retrieve the color values of any pixel on the canvas. Did I tell you that you can also change the color values of pixels on the canvas? I didn’t? Oops! Let’s take a look at that now then, it’s dead cool.


Applying Effects to Images

Now that you’re able to access the pixel color values of the canvas, changing those values is a breeze. In fact, changing those color values is as simple as changing the values in the CanvasPixelArray and then drawing it back onto the canvas. Let’s take a look at how to do that.

The first step is to set up the code as you did in the previous section. This code loads an image, draws it onto the canvas, and then grabs the pixel data:

var image = new Image();
image.src = "sample.jpg";
$(image).load(function() {
    ctx.drawImage(image, 0, 0);

    var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    var pixels = imageData.data;
    var numPixels = imageData.width * imageData.height;
});

So far so good. The next step is to loop through every pixel on the canvas and change its color values. In this example you’re going to invert the colors by deducting the current color value (0 to 255) from 255:

for (var i = 0; i < numPixels; i++) {
    pixels[i*4] = 255-pixels[i*4]; // Red
    pixels[i*4+1] = 255-pixels[i*4+1]; // Green
    pixels[i*4+2] = 255-pixels[i*4+2]; // Blue
};

There’s nothing crazy going on here; you’re simply multiplying the pixel number (i) by 4 to get the index of the red color value for that pixel in the CanvasPixelArray. By adding 1 or 2 to that number you can get and change the green and blue color values respectively.

Finally, all you need to do now is to clear the canvas (to get rid of the normal image), and then use the putImageData method of the 2d rendering context to draw the saved CanvasPixelArray to the canvas:

ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.putImageData(imageData, 0, 0);

And that’s honestly all there is to it; reload your browser and take a look for yourself. Cool, isn’t it?

Inverting the pixels of an image

Wrapping Things Up

There is so much more to pixel manipulation in canvas, but I hope that you’ve experienced enough in this article to get your juices flowing. I encourage you to explore this area further and see what else you can do with pixels. Why? Because all of the techniques that you leant about pixel manipulation can be used for HTML5 video as well as images. Now that’s cool!

In the next article, the final one in this series, we’ll be taking a different look at canvas. This time, you’ll learn how to animate on the canvas, which will give you the basics required to create cartoons, animations, and games. This is undoubtably my favorite use of canvas.

April 20 2011

15:04

Canvas From Scratch: Transformations and Gradients


In this article, I’m going to walk you through transformations in the canvas, as well as shadows and gradients. Transformations are an extremely valuable set of methods that allow you to start being creative with the way you draw objects on the canvas. Let’s get started after the jump!


Setting Up

You’re going to use the same HTML template from the previous articles, so open up your favourite editor and paste in the following code:

<!DOCTYPE html>

<html>
    <head>
        <title>Canvas from scratch</title>
        <meta charset="utf-8">

        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>

        <script>
            $(document).ready(function() {
                var canvas = document.getElementById("myCanvas");
                var ctx = canvas.getContext("2d");
            });
        </script>
    </head>

    <body>
        <canvas id="myCanvas" width="500" height="500">
            <!-- Insert fallback content here -->
        </canvas>
    </body>
</html>

Here we have nothing more than a basic HTML page with a canvas element and some JavaScript that runs after the DOM has loaded. Nothing crazy.


Translations in Action

Translate essentially shifts the entire coordinate system.

One of the simplest transformations in canvas is translate. This allows you to move the origin point of the 2d rendering context; the (0, 0) position on the canvas. Let me show you what this means.

First, place a square in canvas at the position (0, 0):

ctx.fillRect(0, 0, 100, 100);

It will draw itself at the top left hand edge of the canvas. Still – nothing out of the ordinary here.

A simple square

Now, try translating the 2d rendering context and drawing another square in the same position:

ctx.save();
ctx.translate(100, 100);
ctx.fillStyle = "rgb(0, 0, 255)";
ctx.fillRect(0, 0, 100, 100);
ctx.restore();

What do you think will happen? Have a gold star if you guessed that the new square will be drawn at the position (100, 100). No play time for those who guessed wrong. Sorry!

Translating a square

So what happened here then? As far as the code for drawing the second square is concerned, you drew it in the same place as the first square. The reason for this is that you basically shifted the entire coordinate system of the canvas so that its (0, 0) position is now at the place (100, 100).

How translation works

Does it make a little more sense now? I hope so. It can take a little while to get your head around, but it’s a simple concept once you understand it.

You probably wouldn’t use this transformation too much on its own, as you could simply draw the second square at (100, 100) to get the same effect. The beauty of translate, though, is that you can combine it with other transformations to do some pretty cool things.

Let’s take a look at the next transformation on the list.


Scaling Your Visuals

As you’ve probably guessed, the scale transformation is used for resizing. More specifically, the scale transformation is used to scale the 2d rendering context.

Remove the code that you worked on with the translate example, and add the following code:

ctx.fillRect(100, 100, 100, 100);

This will draw a standard square at the position (100, 100), with a width and height of 100 pixels. So how do we scale this?

A simple square

Properties in scale are multipliers for the x and y dimensions.

The scale transformation is used in a similar way to translate, in that it’s called before you draw the objects that you want it to be applied to. It’s important to point out that the properties in scale are multipliers for the x and y dimensions. This means that a scale of (1, 1) would multiply the size of the 2d rendering context by one, leaving it the same size it was before. A scale of (5, 5) would multiply the size of the 2d rendering context by five, making it five times larger than it was previously. Simple.

In your case you want to double the size of the square, so you apply a scale of (2, 2):

ctx.save();
ctx.scale(2, 2);
ctx.fillRect(100, 100, 100, 100);
ctx.restore();

Which results in a square that is two times the size:

Scaling a square

However, notice how the square is now being drawn in a different position than it was being drawn before you applied scale. The reason for this is that scale multiplies the size of everything in the 2d rendering context, including coordinates. In your case, the position (100, 100) now becomes (200, 200); the coordinates are twice the size that they would be without being scaled.

To get around this, we can perform a translate that moves the origin of the 2d rendering context to the position that you want to draw the square. If you then apply scale and draw the square at position (0, 0), its position won’t be shifted:

ctx.save();
ctx.translate(100, 100);
ctx.scale(2, 2);
ctx.fillRect(0, 0, 100, 100);
ctx.restore();

Which results in a square that is twice as large as the original, but that is drawn at the same position as the original:

Scaling and translating square

It’s being aware of these little quirks in transformations that really helps when using them. Most of the common issues with transformations seems to be a result of not fully understanding how they work.


Rotating Elements

So far, all the transformations that you’ve dealt with have been pretty unexciting. Fortunately, the rotate transformation is here to save the day, and it’s easily my favourite of the bunch.

I’m sure rotate needs no introduction, so let’s jump right in and rotate a square 45 degrees (remember that degrees need to be in radians):

ctx.save();
ctx.rotate(Math.PI/4); // Rotate 45 degrees (in radians)
ctx.fillRect(100, 100, 100, 100);
ctx.restore();

Which positions a square at (100, 100) and rotates.. woah, hang on! This doesn’t look right:

Rotating a square

See what happened? The square seems to be trying to escape the browser window, rather than rotating on the spot at the position (100, 100). This is because rotate, like all the transformations, affects the entire 2d rendering context, and not objects individually.

Here is an illustration of what happens to the coordinate system when you perform a 45 degree rotate:

How rotation works

Notice how the entire coordinate system has rotated 45 degrees from the point of origin (0, 0)? This is what caused the square to look like it was escaping the browser window, simply because the position (100, 100) had been rotated slap bang on the edge of the browser.

The simple way to get around this issue is to combine rotate with translate, like so:

ctx.save();
ctx.translate(150, 150); // Translate to centre of square
ctx.rotate(Math.PI/4); // Rotate 45 degrees
ctx.fillRect(-50, -50, 100, 100); // Centre at the rotation point
ctx.restore();

Performing the translate moves the origin point of the 2d rendering context (0, 0) to what should be the central point of the square (150, 150). This means that any rotation will now be based around the position (150, 150). If you then draw a square with a negative x and y position, equal to half of the square’s width and height, you’ll end up drawing a square that looks like it has been rotated around its central point:

Rotating and translating a square

The rotate transformation is likely the hardest of them all to understand fully. It’s important to remember that transformations are performed on the entire 2d rendering context, and, if you want to rotate a shape around its central point, you’ll need to combine rotate with translate.

Let’s move onto something a bit more visually impressive.


Adding Shadows

Adding shadows to objects is delightfully simple.

Canvas comes supplied with a few properties for manipulating the appearance of the objects that are drawn on it, and one set of these properties allows you to add shadows.

Adding shadows to objects is delightfully simple. It simply requires the shadowColor property to be set on the 2d rendering context to a colour that isn’t transparent black, and either of the shadowBlur, shadowOffsetX, or shadowOffsetY properties to be set to a value other than 0.

Try out the following code:

ctx.save();
ctx.shadowBlur = 15;
ctx.shadowColor = "rgb(0, 0, 0)";
ctx.fillRect(100, 100, 100, 100);
ctx.restore();

This will give the shadow a fifteen pixel blur, and will set the colour to solid black:

Adding a blurred shadow

Pretty standard stuff so far.

If you set the shadowBlur to 0, change the shadowColor to a light grey, and give a positive shadowOffsetX and shadowOffsetY:

ctx.save();
ctx.shadowBlur = 0;
ctx.shadowOffsetX = 6;
ctx.shadowOffsetY = 6;
ctx.shadowColor = "rgba(125, 125, 125, 0.5)"; // Transparent grey
ctx.fillRect(300, 100, 100, 100);
ctx.restore();

You’ll end up with a solid shadow that appears slightly to the right and below the object that has been drawn:

Adding a solid shadow

As cool as shadows are, they can be a bit of a resource hog.

It’s important to remember that shadows affect everything that is drawn after they are defined, so it’s useful to use the save and restore methods to save you from having to reset the shadow properties once you’ve used them.

Keep in mind that performance can suffer when you’re applying a shadow to lots and lots of objects at the same time. In some cases, it might be worth using a PNG image with a shadow instead of drawing an object manually and applying a dynamic shadow using code. We’ll cover how to use images with canvas in the next installment of this series.


Creating Gradients

You can create two types of gradients in canvas – linear and radial.

The last features that I want to cover with you in this tutorial are gradients. There are two types of gradients in canvas, the first being linear (straight) gradients. You can create a linear gradient using the createLinearGradient method (surprisingly enough), which looks like this in pseudo-code:

ctx.createLinearGradient(startX, startY, endX, endY);

The first set of two arguments are the x and y position of the start of the gradient, and the second set of arguments are the x and y position of the end of the gradient. It’s also important to point out that a gradient in canvas is actually a type of colour value, so you apply them to the fillStyle and strokeStyle properties.

Here is an example of how to create a linear gradient that runs from the top of the canvas, all the way to the bottom:

var gradient = ctx.createLinearGradient(0, 0, 0, canvas.height);
gradient.addColorStop(0, "rgb(255, 255, 255)");
gradient.addColorStop(1, "rgb(0, 0, 0)");

ctx.save();
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.restore();

Notice how you assign the gradient to a variable, then use that variable to call the addColorStop method. This method allows you to set the colour at particular points along the gradient. For example, the position 0 would represent the start of the gradient (the first x and y position), and 1 would represent the end of the gradient (the second x and y position). You can also use decimal points between 0 and 1 to assign a colour at a different point along the gradient, like 0.5 would be half way along.

By applying the gradient variable to the fillStyle property, you end up with a nice gradient that goes from white (at position 0 at the top of the canvas), to black (at position 1 at the bottom of the canvas):

Creating a linear gradient

But you don’t always have to use linear gradients; you can also create radial gradients!

Radial gradients are created with the createRadialGradient method, which looks like this in pseudo-code:

ctx.createRadialGradient(startX, startY, startRadius, endX, endY, endRadius);

The first set of three arguments are the x and y position as well as the radius of the circle at the start of the gradient, with the final three arguments representing the x and y position as well as the radius of the circle at the end of the gradient.

Sound confusing, right? It is a bit, so let’s jump in and create a radial gradient to see what happens:

var gradient = ctx.createRadialGradient(350, 350, 0, 50, 50, 100);
gradient.addColorStop(0, "rgb(0, 0, 0)");
gradient.addColorStop(1, "rgb(125, 125, 125)");

ctx.save();
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.restore();

You’ve created a radial gradient that has a starting point at (350, 350) with a radius of 0, and an ending point at (50, 50) with a radius of 100. Can you guess what this will look like? 20 points if you guessed it would look like this:

Creating a radial gradient

If you’re anything like me, that’s not what I expected to see. I’ve used radial gradients before in applications like Adobe Photoshop, and they look nothing like that! So why does it look like this then? Well, that’s what it’s meant to look like, weirdly.

Check out this diagram that depicts exactly how a radial gradient works in canvas:

How radial gradients work

Interesting, isn’t it? It basically allows you to create a cone shape, but what if you want to create a proper radial gradient like the one in Photoshop? Fortunately, it’s simple.

Creating a proper radial gradient just requires you to place the two circles of the gradient at exactly the same x and y position, making sure that one of the gradient circles is larger than the other:

var canvasCentreX = canvas.width/2;
var canvasCentreY = canvas.height/2;

var gradient = ctx.createRadialGradient(canvasCentreX, canvasCentreY, 250, canvasCentreX, canvasCentreY, 0);
gradient.addColorStop(0, "rgb(0, 0, 0)");
gradient.addColorStop(1, "rgb(125, 125, 125)");

ctx.save();
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.restore();

The code above creates a radial gradient that sits at the centre of the canvas. One of the circles in the gradient has a radius of 0, while the other has a radius of 250. The result is a traditional radial gradient that travels from the centre of the canvas outwards, like so:

Creating a radial gradient

That looks better! I was honestly amazed when I saw how radial gradients were implemented in canvas. I bet it’s tripped a lot of people up when they see that cone shape. Oh well, at least you know how to create proper ones now.

It’s worth pointing out that gradients in canvas are also quite intensive operations. If you want to cover the entire canvas in a gradient, I’d first consider applying a CSS3 gradient background to the canvas element itself.


Wrapping Up

In this article, we reviewed how to perform basic transformations on the canvas, including translations, scaling, and rotation. You also learned how to add shadows to objects, and how to create gradients. It doesn’t sound like like much, but transformations, in particular, form the backbone of some of the coolest stuff that can be achieved in canvas.

In the next entry in “Canvas from Scratch”, we’re going to break away from drawing objects and take a look at how to manipulate images and video in the canvas. This is where things start to get really interesting! Stay tuned!

March 13 2011

03:05

Canvas From Scratch: Advanced Drawing


In the previous article in this series, you learned about the canvas element, and the basics for drawing on it. In this article, I’m going to demonstrate some of the more advanced drawing functionality.


Setting Up

We’ll use the same HTML template from the previous article; so open up your favorite editor and paste in the following code:

<!DOCTYPE html>

<html>
	<head>
		<title>Canvas from scratch</title>
		<meta charset="utf-8">

		<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>

		<script>
			$(document).ready(function() {
				var canvas = document.getElementById("myCanvas");
				var ctx = canvas.getContext("2d");
			});
		</script>
	</head>

	<body>
		<canvas id="myCanvas" width="500" height="500">
			<!-- Insert fallback content here -->
		</canvas>
	</body>
</html>

This is nothing more than a basic HTML page with a canvas element and some JavaScript that runs after the DOM has loaded. Nothing crazy.


Drawing Circles

In the last article I showed you how to draw basic shapes and paths; in this section I’m going to show you how to take things a step further and draw circles. It’s not as easy as you might think, but it’s still not hard at all.

There isn’t a method in canvas that lets you draw a circle with a single line of code, like how fillRect works for rectangles. Instead, you have to draw circles with a path using the arc method; a circle is merely a 360 degree arc. The reason for this is that circles are actually very complex shapes, and the arc method allows for all sorts of control over the way that you draw them. For example, you might want to only draw a semi-circle. The arc method allows you to do that. You could even combine the arc method with standard straight paths to draw pizza slices and quarter circles.

I’ll explain how the arc method works shortly, but for now, let’s draw a circle by adding the following code underneath the ctx variable:

context.beginPath();
context.arc(100, 100, 50, 0, Math.PI*2, false);
context.closePath();
context.fill();

This will draw a circle positioned slightly away from the top left of the canvas:

Looks simple, right? And it is, but let’s take a closer look at what’s going on.

The arc method has a total of six arguments:

  • The first is the x position of the origin point (the centre of the circle).
  • The second is the y position of the origin point.
  • The third is the radius of the circle.
  • The forth is the start angle of the circle.
  • The fifth is the end angle of the circle.
  • And sixth is the direction to draw the arc (true is anti-clockwise, and false is clockwise)

Written in pseudocode, arc would look like this:

arc(x, y, radius, startAngle, endAngle, anticlockwise);

The first three arguments are self-explanatory, as is the last, but what about the start and end angle? Let me explain.

As I mentioned previously, circles are just 360 degree arcs. In canvas, an arc is defined as a curved line that starts at a distance away from an origin point that is the distance of the radius. The curved line starts at the angle defined as the start angle argument (the forth one), and continues around the circumference of an imaginary circle until it reaches the angle defined as the end angle argument (the fifth). Sounds simple, right?

Perhaps an illustration will help explain the situation:

It may look crazy, but it makes a lot of sense once you’re able to get your head around it.

Angles in canvas

At this point, it’s probably worth mentioning that angles in canvas are done in radians, not degrees. This means that angles go from 0 to pi multiplied by two. Angles in canvas also start from the right hand side, as can be seen in the following illustration:

If you really don’t like radians, you can easily convert degrees into radians with the following JavaScript formula:

var degrees = 270;
var radians = degrees * (Math.PI / 180);

This formula is dead simple and it’s extremely valuable if you want to deal in degrees.


Bézier Paths

Arcs are fun and all, but they’re pretty limiting for the kind of curves that can be created with canvas. For anything more complex, you’ll want to start looking at the Bézier curve methods quadraticCurveTo, and bezierCurveTo. These methods allow you to create curved paths that have a radius that isn’t central to the curve, and also to create paths that have multiple curves.

Bézier paths use control points to define how and where to draw the curves. For example, quadraticCurveTo has one control point, whereas bezierCurveTo has two. Check out the following illustration to see how the control points affect the way a curve is drawn:

If you’ve used a vector-based drawing application like Adobe Illustrator before, then you might already be comfortable with these kinds of curves.

Let’s jump in and create a quadratic BŽzier path. Replace the arc code with the following:

ctx.lineWidth = 8;
ctx.beginPath();
ctx.moveTo(50, 150);
ctx.quadraticCurveTo(250, 50, 450, 150);
ctx.stroke();

This will draw a curved path that looks like the one on the left of the illustration above:

The quadraticCurveTo method takes four arguments:

  • The first is the x position of the control point.
  • The second is the y position of the control point.
  • The third is the x position of the end of the path.
  • And the forth is the y position of the end of the path.

Written in pseudocode, quadraticCurveTo would look like this:

quadraticCurveTo(cpx, cpy, x, y);

The start position of the curve is wherever the path currently lies. For example, in the code above you moved the start of the path by calling the moveTo method.

Let’s step up a level a create a cubic BŽzier path. Replace the previous code with the following:

ctx.lineWidth = 8;
ctx.beginPath();
ctx.moveTo(50, 150);
ctx.bezierCurveTo(150, 50, 350, 250, 450, 150);
ctx.stroke();

This will draw a curved path that looks like the one on the right of the illustration above:

The bezierCurveTo method takes six arguments:

  • The first is the x position of the first control point.
  • The second is the y position of the first control point.
  • The third is the x position of the second control point.
  • The forth is the y position of the second control point.
  • The fifth is the x position of the end of the path.
  • And the sixth is the y position of the end of the path.

Written is pseudocode, bezierCurveTo would look like this:

bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);

On their own Bézier paths aren’t super amazing, but when combined with normal paths, or when used multiple times, the results can be pretty profound. They allow you to create all sorts of complicated and crazy shapes in canvas!

You might want to check out the Ai->Canvas plugin for Adobe Illustrator that lets you export your fancy vector drawing as canvas code. It’s pretty neat, and will save you loads of time!


Drawing State

In the previous article in this series, I detailed how to change the fill and stroke style of the canvas, as well as how to change the line width. One of the issues to be aware of when changing these properties is that you’ll have to manually change the colours and line width back again if you want the colour or width that you had originally. Fortunately, as always, there’s a better way to do this; it’s called the drawing state.

The drawing state in canvas is essentially a stack on which you can save the current styles, and then restore them again at a later date.

It’s a deviously simple concept, but one that allows you to do so much when fully understood. In fact, the drawing state holds a massive amount of visual information about the canvas, like the the transformation matrix, the clipping region, and the following properties; globalAlpha, globalCompositeOperation, strokeStyle, fillStyle, lineWidth, lineCap, lineJoin, miterLimit, shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor, font, textAlign, and textBaseline. Most of these will be new to you, so don’t worry. You’ll learn about transformations and other fun stuff like shadows in the next article.

Saving the drawing state

Using the drawing state is dead simple, but understanding it fully can take a bit of time. Replace the code from the last section with the following:

ctx.fillStyle = "rgb(0, 0, 255)";
ctx.save();
ctx.fillRect(50, 50, 100, 100);

That’s genuinely all you need to save the drawing state: a single call to the save method. I told you it was simple!

What’s happening here is that you’re changing the fill style of the canvas to blue, then saving the drawing state, which pushes the current state onto the stack that I was talking about earlier. By default, the stack of drawing states is empty.

It’s important to remember that the stack works just like a stack of paper on your desk; the first item on the stack is at the bottom, with the newest item at the top. If you want to get at the first item again, you have to first take off all of the items on top of it. This is known as a first in last out system, or last in first out if you want to look at it the other way round.

Restoring the drawing state

Saving the drawing state is great and all, but actually using it again is properly a little more useful. To do that, you’re going to use the restore method.

Add the following code to the code above:

ctx.fillStyle = "rgb(255, 0, 0)";
ctx.fillRect(200, 50, 100, 100);

This will draw another rectangle on the canvas, but this time in a different colour (red):

All pretty standard stuff so far, but what if you want to switch back to the blue colour and draw another rectangle? Well, you could set the fill style manually as blue, but that would be boring. Let’s try using the restore method and seeing what happens.

Add the following code:

ctx.restore()
ctx.fillRect(350, 50, 100, 100);

This will draw another rectangle, but this time with the original fill style:

How easy was that? The call to restore pulled out and removed the last drawing state that was added to the stack, and then applied it to the canvas, saving you a whole bunch of time. Ok, well it might not have saved you a massive amount of time in this example, but it would have had you changed all sorts of properties and performed transformations on the canvas.

Using multiple drawing states

So you know how to use the drawing state for a single occurrence, but what happens if you save multiple drawing states? For the sharp-eyed you might remember that I referred to the stack as a pile of paper; last in, first out. Let’s see how this works in code.

Update the previous code to save the drawing state after setting the fill style to red:

ctx.fillStyle = "rgb(0, 0, 255)";
ctx.save();
ctx.fillRect(50, 50, 100, 100);

ctx.fillStyle = "rgb(255, 0, 0)";
ctx.save();
ctx.fillRect(200, 50, 100, 100);

ctx.restore()
ctx.fillRect(350, 50, 100, 100);

Even though this is practically the same code as before, everything will have changed as the latest drawing state added to the stack contains the red fill style:

To restore the first state (the blue fill style), you’ll need to call restore for a second time, so add the following code:

ctx.restore();
ctx.fillRect(50, 200, 100, 100);

This will pull and remove the first state off of the stack and apply it to the canvas, giving you a blue fill style:

By using multiple drawing states like this you can save a whole bunch of time. It’s pretty nifty!


Wrapping Things Up

I hope that I haven’t gone too fast through all of this. Some of the concepts that we’ve covered are pretty advanced, and I’d encourage you to reread the article and play around with the code to get a better understanding of what’s going on.

In the next article you’ll be learning how to perform transformations on the canvas, as well as how to use shadows and gradients. Exciting times!

February 14 2011

00:56

Canvas From Scratch: Introducing Canvas


This is the first article in a series that will bring you up to speed with HTML5 canvas, the plugin-less drawing functionality built into modern browsers. In this introductory article, I’ll show you how to access the canvas element, draw shapes, change colours, and erase things. It’s a whistle-stop tour of the basics of this amazing new Web technology.

The series will be an exciting ride, and one that I hope you enjoy. I’m assuming that you’re already comfortable with JavaScript, but have little to no experience with canvas. Even if you’re new to JavaScript, don’t fret, as you’ll still learn something from these articles.


Introducing the Canvas Element

Using the canvas element is dead easy.

When you think of canvas, you probably think about the new HTML5 canvas element. Technically, this is only one half of the story, but let’s forget about that for now. The canvas element is the public face of this fancy new feature of the browser.

Using the canvas element is dead easy; it’s one simple HTML tag, with a defined width and height.

<canvas width="500" height="500">
	<!-- Insert fallback content here -->
</canvas>

This doesn’t do much yet. In fact, all it does is insert a transparent canvas on your page. The content inside of the canvas element is fallback content, which will only display if a browser doesn’t support canvas.

Browser support

Browser support for canvas is pretty amazing.

It’s important to point out that the browser support for canvas is pretty amazing. Every modern browser supports it, including the latest Internet Explorer.

  • Internet Explorer (9.0+)
  • Safari (3.0+)
  • Firefox (3.0+),
  • Chrome (3.0+)
  • Opera (10.0+)
  • iOS (1.0+)
  • Android (1.0+)

Interestingly, you can use some canvas functionality in Internet Explorer version 8 and below, via the ExplorerCanvas plugin.

Canvas dimensions

One key lesson that I learnt with canvas is that you have to explicitly set the width and height attributes of the canvas element when defining its dimensions. Using CSS to set the width and height will effectively cause the canvas to scale up (or down) to that size. There is a logical reason behind this; it’s to do with the canvas element being a container for something called the 2d rendering context. However, it’s just important to know that using CSS to set the canvas dimensions will have an odd effect.


Discovering the 2d Rendering Context

I mentioned in the last section that the canvas element is only one half of the story. The other half is the 2d rendering context; the part of canvas that lets you do the cool stuff that you can actually see.

Let me make one thing completely clear: when you use canvas, you’re not drawing on the canvas element itself. Instead, you’re actually drawing on the 2d rendering context, which you’re accessing through the canvas element via the JavaScript API. It doesn’t really matter in the grand scheme of things, but it’s useful to know.

Coordinate system

If you’ve used any 2d graphics programming languages before (ActionScript, Processing, etc), then you’ll know all about screen-based coordinate systems. The 2d rendering context in canvas is no different; it uses a standard Cartesian coordinate system, with the origin point (0, 0) at the top left. Moving to the right will increase the value of the x axis, while moving downward will increase the value of the y axis. It’s pretty straightforward.

One unit in the coordinate system is equal to one pixel on the screen (in the majority of cases).

Accessing the 2d rendering context

To actually use the 2d rendering context, you’ll need to use the JavaScript API. The part of the API that you want to use is the getContext method, like so:

<!DOCTYPE html>

<html>
	<head>
		<title>Canvas from scratch</title>
		<meta charset="utf-8">

		<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>

		<script>
			$(document).ready(function() {
				var canvas = document.getElementById("myCanvas");
				var ctx = canvas.getContext("2d");
			});
		</script>
	</head>

	<body>
		<canvas id="myCanvas" width="500" height="500">
			<!-- Insert fallback content here -->
		</canvas>
	</body>
</html>

Note: you’re using jQuery here, but only for checking when the DOM is ready. Feel free to use your favorite JavaScript library instead, or place the code at the bottom of the document.

As a result of calling getContext, the ctx variable will now contain a reference to the 2d rendering context. This means that you now have everything in place to actually start drawing onto the canvas. The fun part!


Drawing Rectangles

Now that you have access to the 2d rendering context, you’re able to start calling the drawing methods of the API. One of the most basic is fillRect, which draws a rectangle that’s filled in a particular colour (black by default).

Add the following code underneath the ctx variable from earlier:

ctx.fillRect(50, 50, 100, 100);

This will draw a black square that is set slightly away from the left and top edges of the canvas, like so:

You’ve just drawn your first shape using HTML5 canvas. Feels good, right?

Note: You’ll notice that you’re using the rectangle method of the JavaScript API to draw squares. This is because there is no methods in canvas to draw squares directly, simple because squares are rectangles (they have four sides with right angles between them).

There are four arguments in a call to fillRect:

  • The first is the x position of the origin point (the top left).
  • The second is the y position of the origin point.
  • The third is the width.
  • And the forth is the height.

Written is pseudocode, fillRect would look like this:

ctx.fillRect(x, y, width, height);

The cool thing is that you’re not limited to just filled rectangles. Nope. You can also draw stroked rectangles; that is, rectangles with an outline around them. To to that you can use the strokeRect method of the JavaScript API, like so:

ctx.strokeRect(50, 50, 100, 100);

It uses exactly the same arguments as fillRect, and the result will be a lovely outline of a square:

Simple. Elegant. Easy. That really sums up canvas. All the methods are straightforward when looked at individually, but when used together they allow you to draw some pretty amazing things.


Drawing Paths

Aside from rectangles (the only shapes that can be drawn with a single API method), you have paths. Paths allow you to draw lines, both straight the curved, that can be combined to create quite complex shapes.

Drawing a simple path requires the use of a few new API methods:

  • beginPath starts a new path.
  • moveTo moves the point that the path is drawn from.
  • lineTo draws a straight path to this point from the point defined in moveTo, or the point from the last call to lineTo.
  • closePath closes the path by connecting the last point to the starting point.
  • fill fills the path with a colour.
  • stroke outlines the path.

Try the following code:

ctx.beginPath();
ctx.moveTo(50, 50);
ctx.lineTo(50, 250);
ctx.lineTo(250, 250);
ctx.closePath();
ctx.fill();

Which will draw a triangle path, and fill it:

You can use the same concept to draw any other shape that you want. The second article in this series will cover more advanced paths in canvas, like arcs (to create circles), and Bezier paths (to create cool curvy lines).

The important thing to remember right now is that paths are pretty much the only way to draw something more complicated than a rectangle.


Changing Colour

So far, everything that you’ve drawn has been filled or stroked in black. How exciting! Fortunately, there are a couple of properties within the JavaScript API that let you change the colour of the shapes that you’re drawing. These properties are fillStyle and strokeStyle.

They’re both pretty self explanatory, so let’s jump in and change the fill colour of a rectangle:

ctx.fillStyle = "rgb(255, 0, 0)";
ctx.fillRect(50, 50, 100, 100);

This will give you a nice red square, like so:

Or, you could change the stoke colour of a rectangle:

ctx.strokeStyle = "rgb(255, 0, 0)";
ctx.strokeRect(50, 50, 100, 100);

Which will give you a square with a red outline:

The beauty of fillStyle and strokeStyle is that they both accept normal CSS colour values. That means you can use RGB, RGBA, HSA, colour words (eg. “red”), and hexadecimal values.

It’s worth pointing that changing the colour in canvas won’t affect anything that has already been drawn. For example, if you draw a black rectangle, then change the fill style to red, then draw another rectangle; the first rectangle will still be black.


Changing Line Width

Aside from changing colour, you can also change the width of a stroked outline. To do this you can use the lineWidth property of the JavaScript API.

Using the code from the previous example, you can change the width of the outline:

ctx.lineWidth = 20;
ctx.strokeStyle = "rgb(255, 0, 0)";
ctx.strokeRect(50, 50, 100, 100);

Which will give you a beautiful and chunky red stroke:

The same concept works for paths as well. For example, you can change the triangle from earlier to have a thicker outline:

ctx.lineWidth = 20;
ctx.beginPath();
ctx.moveTo(50, 50);
ctx.lineTo(50, 250);
ctx.lineTo(250, 250);
ctx.closePath();
ctx.stroke();

Which will give you an incredibly exciting chunky triangle:

There are also some other features of the JavaScript API that let you change the way lines are drawn. For example, lineCap changes the way the end of a line looks, and lineJoin changes the way the corners in a line look. You should definitely check out these features (and more) in the canvas specification.


Erasing the Canvas

The last thing that I want to teach you is how to erase the canvas. You’ve learnt how to draw shapes, but not how to actually get rid of them, which can be pretty darn useful.

Fortunately, erasing the canvas is easy; you just need one method from the JavaScript API. That method is clearRect, and its job is to make every pixel within the rectangle transparent.

In this article, the canvas is 500 pixels wide, and 500 pixels tall, so you could easily erase the entire canvas by calling clearRect like so:

ctx.fillRect(50, 50, 100, 100);
ctx.clearRect(0, 0, 500, 500);

There’s no use showing you a screenshot of this, because if it worked you should see absolutely nothing. The filled rectangle is actually being drawn, but it’s instantly being cleared afterward, so you don’t get to see it.

Note: The arguments in clearRect are the same as fillRect; x, y, width and height.

If you’re not sure of the width and height of the canvas, you can also erase it like so:

ctx.clearRect(0, 0, canvas.width, canvas.height);

This uses the width and height properties of the canvas element itself, which is incredibly useful and a much better way of doing things.

Erasing a small section of the canvas

You don’t have to erase the entire canvas if you don’t want to. You can quite easily erase just a small portion instead. For example, imagine you had a black square drawn next to a red square:

ctx.fillRect(50, 50, 100, 100);
ctx.fillStyle = "rgb(255, 0, 0)";
ctx.fillRect(200, 50, 100, 100);

Which would normally look like this:

You could erase the black square and leave the red square intact by adding a call to clearRect underneath:

ctx.clearRect(50, 50, 100, 100);

Notice how this call to clearRect defines a position and size that is the same as the black square. This basically means that it will only change the pixels in the area of the square to transparent black (erasing them):

Pretty nifty, isn’t it? Erasing the canvas is not something that you’ll use much with static drawings, but it’s something that you’ll be using a lot of when you learn how to animate later in this series.


Wrapping Things Up

Canvas is easy to use, quick to learn, and dead powerful when you push it to the limits.

So, as I hope you can see, canvas is a particularly potent new part of the browser. It allows you to create graphics, using code, and without using a single plugin. It’s easy to use, it’s quick to learn, and it’s dead powerful when you push it to the limits.

In the next article, you’ll be looking at some of the more advanced features of canvas, like drawing circles, curved paths, and something called the drawing state. And if that isn’t enough, later on in the series you’ll be looking at how to transform drawings (like rotation and scale), how to manipulate images, and ending with a look at how to animate. It’s going to be very exciting stuff, trust me.

For now, I hope that I’ve given you enough to whet your appetite for canvas and to go out and learn more about it. Canvas is a fantastic technology that’s really worth understanding, even if you don’t plan to use it right away.

February 07 2011

05:24

Build a Canvas Image Editor with Canvas: New Premium Tutorial


The HTML5 canvas element makes so many things possible: animation, graphing and data visualisation, gaming, and much more. One thing it makes possible is the creation and manipulation of images. And when I say manipulation, I mean true pixel-level manipulation. In this Premium tutorial and companion screencast, we’ll build a basic image manipulator implemented using the canvas element.

Become a Premium member to read this tutorial, as well as hundreds of other advanced tutorials and screencasts.


Join Net Premium

NETTUTS+ Screencasts and Bonus Tutorials

For those unfamiliar, the family of Tuts+ sites runs a premium membership service. For $9 per month, you gain access to exclusive premium tutorials, screencasts, and freebies from Nettuts+, Psdtuts+, Phototuts+, Aetuts+, Audiotuts+, Vectortuts+, and CgTuts+ For the price of a pizza, you’ll learn from some of the best minds in the business. Become a Premium member to read this tutorial, as well as hundreds of other advanced tutorials and screencasts.

January 07 2011

16:53

November 23 2010

20:24

How to Generate Noise with Canvas


Not too long ago, I noted on Twitter that it’d be fantastic if, one day, CSS3 provided support for adding noise to elements (not audio, but texture). After a bit of experimentation and Googling, I came across a solution that uses JavaScript and canvas to dynamically create noise.


The Screencast

Press the HD button for a clearer picture.

Subscribe to our YouTube page to watch all of the video tutorials!


Final Source

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>Noise</title>
</head>
<body>

   <script>
      function generateNoise(opacity) {
         if ( !!!document.createElement('canvas').getContext ) {
            return false;
         }
         var canvas = document.createElement('canvas'),
            ctx = canvas.getContext('2d'),
            x, y,
            r, g, b,
            opacity = opacity || .2;

         canvas.width = 55;
         canvas.height = 55;

         for ( x = 0; x < canvas.width; x++ ) {
            for ( y = 0; y < canvas.height; y++ ) {
               r = Math.floor( Math.random() * 255 );
               g = Math.floor( Math.random() * 255 );
               b = Math.floor( Math.random() * 255 );

               ctx.fillStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + opacity + ')';
               ctx.fillRect(x, y, 1, 1);
            }
         }

         document.body.style.backgroundImage = "url(" + canvas.toDataURL("image/png") + ")";
      }

      generateNoise(.1);
   </script>
</body>
</html>

Conclusion

The big question: is it practical to use a solution like this? Ehh — technically, sure. Browsers that don’t support canvas will simply display a solid background color. That being said, a tiny 24-bit PNG still works perfectly, and is what I’ll most likely continue to use until a more convenient solution becomes available.

What do you think? Or better yet, do you know of a better solution? Mostly, the purpose of this tutorial is mostly to work with canvas a bit, and toy around with things! Thanks for watching, and thank you to Mitch Johnson for the concept.

October 09 2010

15:19

Normal Mapped Lighting for Photos using Canvas

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!

September 14 2010

11:00

“Or so they say…” by Mr. Doob

Via Mr. Doob comes a cool canvas demo called "Or so they say..." he created. What's interesting about this demo is it uses HTML5 Audio and Canvas, including Mr. Doob's Three.js library and sequencer that he also used on The Wilderness Downtown project.

Three.js is similar to Papervision3D in the Flash world, allowing you to build up 3D scenes. Three.js then draws the 3D scene graphs using either Canvas, SVG, or WebGL. It's a very interesting library, but needs more docs (hint hint Mr. Doob!).

In the "Or so they say..." demo (source), Mr. Doob starts by setting up Three.js, the camera, and the backing renderer:

JAVASCRIPT:
container = document.createElement( 'div' );

camera = new THREE.Camera( 60, 800 / 600, 1, 20000 );

renderer = new THREE.CanvasRenderer();
renderer.setSize( 800, 600 );
renderer.autoClear = false;
container.appendChild( renderer.domElement );
 

The sequencer is then initialized and various 3D and time effects are added; a small snippet:

JAVASCRIPT:
sequencer = new Sequencer();

sequencer.add( new Vector3TravelEffect( camera.position, new THREE.Vector3( 0, 0, 200 ), new THREE.Vector3( 0, 0, 10000 )  ), keys[ 0 ] - 1, keys[ 1 ] - 1 );
sequencer.add( new Vector3TravelEffect( camera.target.position, new THREE.Vector3(), new THREE.Vector3() ), keys[ 0 ] - 1, keys[ 1 ] - 1 );
sequencer.add( new Part1Effect( camera, renderer ), keys[ 0 ], keys[ 1 ] );

sequencer.add( new Vector3TravelEffect( camera.position, new THREE.Vector3( 0, 0, 1000 ), new THREE.Vector3( 0, 0, 400 ) ), keys[ 1 ] - 1, keys[ 2 ] - 1 );
sequencer.add( new Vector3TravelEffect( camera.target.position, new THREE.Vector3(), new THREE.Vector3() ), keys[ 1 ] - 1, keys[ 2 ] - 1 );
sequencer.add( new Part2Effect( camera, renderer ), keys[ 1 ], keys[ 2 ] );
 

The audio is straightforward:

JAVASCRIPT:
audio = document.getElementById( 'audio' );
audio.currentTime = keys[ key ] / 1000;
audio.play();
 

Mr. Doob has some notes about performance:

It's all software rendering (no WebGL), so don't expect much performance. It's running at 20-30fps on my Mac Mini Core 2 Duo @ 2.53Ghz with Ubuntu/Linux. If you are running MacOS. I'm sorry to say that it won't run faster than 1fps... For some reason Chrome team decided to use CoreGraphics instead of Skia.

September 10 2010

10:30

HTML5 Canvas Image Effects: Black & White

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]

September 03 2010

01:51

How to Create a Web-Based Drawing Application Using Canvas: New Premium Tutorial


Combining HTML with the all new <canvas> feature, you can make some pretty awesome web apps! In this Premium exclusive tutorial, we will create a neat interactive drawing application using HTML and JavaScript. Along the way, we’ll also learn the basic concepts of the all new <canvas> feature. Become a Premium member to access this, as well as many other amazing tutorials and screencasts.

Preview
Preview
Preview
Preview

Join Net Premium

"NETTUTS+

For those unfamiliar, the family of Tuts+ sites runs a premium membership service. For $9 per month, you gain access to exclusive premium tutorials, screencasts, and freebies from Nettuts+, Psdtuts+, Aetuts+, Audiotuts+, and Vectortuts+! For the price of a pizza, you’ll learn from some of the best minds in the business. Become a Premium member.

September 01 2010

06:30

21 Ridiculously Impressive HTML5 Canvas Experiments


HTML5 is the thing to talk about these day. Today, we have a collection of some ridiculously impressive HTML5 canvas-based experiments that will make you say, “Wow!” Let’s take a peek at some of the latest, cutting edge examples out there.


1. 8 Bit Color Cycle


2. Particle Letter Animation


3. Cloth Experiment

This is one of the best canvas-based experiments.


4. Particle System

This is one of my favorites — absolutely amazing!


5. Strange Attractors

This example generates beautiful fractals, like the ones generated by Apophysis. Be sure to tick the composite :) .


6. Canvas Nebula


7. Bomomo


8. Liquid Particles


9. Fake Floor Reflections


10. Sinous

This is a really fun game; is it not as easy as it looks!


11. Water in HTML5


12. Blob


13. Magnetic System


14. Trail


15. Particles


16. Shattering Box Physics Simulation

This incredible example depicts real world physics in action.


17. Flower Power

Try to guess the word. :P


18. 9Elements Particle Play

This is a beautiful example which demonstrates audio and canvas in action.


19. Beauty of Maths


20. Tree


21. Cloth Simulation

So what do you think? Getting your own ideas for a neat canvas application? Well, now you have more than one reason to create HTML5 apps: CodeCanyon just launched an HTML5 category! Have fun!

August 30 2010

11:00
10:00

View Source Tutorial: Content Site Using HTML5 Canvas + CSS3

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.

August 25 2010

10:00

Real World Canvas Tips from Hakim El Hattab

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.

August 22 2010

19:30

Want to pack JS and CSS really well? Convert it to a PNG and unpack it via Canvas

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.

Older posts are this way If this message doesn't go away, click anywhere on the page to continue loading posts.
Could not load more posts
Maybe Soup is currently being updated? I'll try again automatically in a few seconds...
Just a second, loading more posts...
You've reached the end.
(PRO)
No Soup for you

Don't be the product, buy the product!

close
YES, I want to SOUP ●UP for ...