Canvas – Drawing on Images

This project adds an additional canvas function, some basic animation and does a little sculpting of randomness.

The new canvas function is

drawImage(image, x, y)
which draws an image on the canvas at coordinates x,y

to draw an image it needs to be loaded. One way to do this is load it from the same directory as the HTML and JavaScript:

var canvas, ctx;
var img = new Image();
img.src = 'skyline.jpg'; 
img.onload = init;

function init(){
    canvas = document.getElementById("canvas");
    ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0);
}

Images loaded this way load asynchronously, which means they may not be completely loaded when drawImage is called. Telling the img object to call a function after the load is completed avoids that problem.

It’s also possible to pre-load the image with a data url, which is the raw image bits encoded in a string, e.g.:

img.src = ‘data:image/jpeg;base64,/9j/4QAYRXhpZgAA….’;

Places like DataURL.net allow uploading images and offer a conversion service. However, this can also be done easily using the canvas. After loading the image using the first example:

var dataURL = canvas.toDataURL('image/jpeg', 0.2); // override default png and
// specify jpg quality 0..1
tb = document.createElement("textarea");
document.body.appendChild(tb);
tb.value = dataURL;

The encoded string for a jpg image can then be copied from the textarea on the page and pasted into a img.src=”; statement.

The downsides are that embedding images this way can result in a quite a large chunk of text in the code and they aren’t cached by the browser. The advantages are no waiting for images to load, they can be used immediately, and the images don’t need to be hosted externally.

Using an image as a backdrop, effects can be created by drawing rectangles with colors and opacity settings on top.

The CityScape

One idea for using images and rectangles was to find an image of a skyline, with silhouettes of buildings, and then add blinking windows to them using small rectangles.

I brought the image into Photoshop and used the rectangular selection marquee to plot out the areas where the “windows” should go.

2015-09-23_162504

By drawing the marquee and then selecting Transform (Ctl or Cmd T) the info box populates both the height and width of the rectangle as well as the x,y origin point of the top left.

The areas can then be mapped as entries in a JavaScript array:

areas = [
    {x:0,y:219, w:17, h:38}, {x:39, y:227, w:30, h:30},
    {x:80, y:233, w:11, h:47}, {x:101, y:163, w:21, h:111} 
];

A function can be written that will take this area and for each area, draw however many rectangles will fit with coordinates inside the area.

The next task is to make the rectangles blink on an off and this introduces a very important tool for generative art: animation.

We need a loop that will run continuously and update the canvas each time it is called. The modern approach to this is via:

RequestAnimationFrame(callback)
tell the browser to call the function “callback” before the next canvas repaint

So setting up a basic loop that will continuously call the draw function to update the canvas:

window.requestAnimationFrame(draw); // call draw before next canvas repaint
function draw() {
     // do canvas draw stuff  
    window.requestAnimationFrame(draw); // call draw again before next repaint
}

If things are running optimally the draw() function will generally be called about 60 times a second.

The final construct needed to implement CityScape was a way to control the random toggling of lights on and off. If random() was used each time the draw() function was called, 60 times a second, it would just be a spastic jitter. To slow it down, the random behavior needs to be tweaked to be a little less uniform. Shaping randomness in various ways is very useful in tuning the aesthetics of its contribution to a piece. In this case, it toggles a light on or off only a small fraction of the time:

if (Math.random() < 0.005) {
    rects[i].d = !rects[i].d;
}

If something needed to happen only 1 every 10 times:

if (Math.random() < 0.1) {
    rects[i].d = !rects[i].d;
}

Since random() returns floating point numbers fairly uniformly between 0 and 1, the above would be true only 10% of the time.

Putting these new constructs together into a finished piece:

See the Pen Canvas – Drawing on Images by Kentskyo (@kentskyo) on CodePen.0

 

 

 

 

Canvas – The Beginning

This is an expedition into generative art using JavaScript and the HTML canvas. It is not, however, an HTML or JavaScript tutorial. It’s a diary of a deep dive into both the nature of generative art and the use of canvas for its expression. Putting it in writing, and words, helps me bring clarity to my journey. But a collateral audience might be someone who knows a little JavaScript, or is willing to pick up the basics, and who wants to explore the possibilities of creating art with code with me. If that’s you, welcome!

To me, generative art is a form that plays in the borders between intent and discovery. I will try to articulate my thoughts on this in time. There is something very special, I think, in the disciplines and boundaries that play between rules and chaos, between control and freedom.

The approach for this series is old school. There are a gazillion libraries, engines and frameworks that offer to make working with canvas easier. But the canvas api is not all that difficult and working with it directly imparts a certain economy and precision.

Creating visual designs this way requires only a simple page of minimal HTML with a canvas tag:

<!DOCTYPE html>
<html lang="en">
<head>
<title>Canvas Example</title>
</head>
<body>
<canvas id="canvas" width="150" height="150"></canvas>
</body>
</html

The <canvas> tag really only has two attributes, width and height, and they are optional, defaulting to 300 and 150 pixels respectively. There’s a third attribute: “id”, which is not really a canvas property per se but a handle HTML uses to reference it from JavaScript or CSS.

To draw something on the canvas with code requires a little JavaScript and it can be included from a file:

<!DOCTYPE html>
<html lang="en">
<head>
<title>Canvas Example</title>
</head>
<body>
<canvas id="canvas" width="150" height="150"></canvas>
<script src="draw.js"></script>
</body>
</html

The <script> tag loads the file “draw.js” from the same directory as the html page and executes it.

Since this isn’t a tutorial on HTML, CSS or JavaScript, here are a few external links if you are just getting up to speed:

For Programmers: Speaking JavaScript
Non-programmers: A Smarter Way to Learn JavaScript

&  A Smarter Way to Learn HTML and CSS

You won’t need too much to start and it may be better to learn what you need as you go rather than over prepare.

There are many ways to work with JavaScript code via editors, development environments and the like. These projects in canvas, however, can be done entirely inside the chrome browser using the Google Dev Editor for Chrome.

They can also be done in online sandboxes. For example, I’ll be using CodePen to publish the code and results and embed them here in the blog. The only reason I don’t do the whole thing in CodePen is I like the ability to doodle with code art in coffee shops and odd places that don’t always have internet connections. I know, heresy, but such places actually exist especially as I do most of my work/play out of the country (USA.) Instant access also rewards working in small time slices when the opportunity arises, although it’s almost guaranteed that you’ll get pulled into something deep at some point or another if you engage in this activity that will in turn create flow states of hours of fascinated absorption.

With the preamble out of the way, it’s time to dive in.

The canvas tag defines a rectangular surface with dimensions of height and width in a browser that code can then scribble on. The canvas coordinate system starts with x=0 and y=0 in the top left corner of the canvas. So a canvas with a height and width of 150 pixels would have these x,y coordinates:

coords
To start drawing on the canvas JavaScript needs a reference to the canvas tag using its “id” attribute. There can be multiple canvases on a page, each with different ids. Obtaining the reference is illustrated in the following code, which first grabs the  canvas id and then uses it to create a drawing context:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

ctx is assigned a canvas context; a context returns different tools based on whether it is writing to a canvas in 2d mode, which is the most widely supported, or 3d, also known as webgl which later projects will delve into.

Using the ctx object returned from the request, we can access functions which will write directly on the canvas.

And this is enough of a start to make something interesting. In generative art, it’s often fun to start with just a handful of elements and constraints and see what happens. This project will use only:

  • rectangles and the 3 functions that draw rectangles in the canvas api
  • colors – for both the strokes (the outline) and the fills (inside area) of the rectangles
  • random numbers – injecting the essential “discovery” element into the generative art piece
  • and nothing else, canvas-wise

A rectangle is the “hello world” of canvas drawing; there are 3 functions that create them:

fillRect(x, y, width, height)
draws a rectangle filled with the current fillStyle, defaults to black if no fill was specified.

strokeRect(x, y, width, height)
draws a rectangular outline with the current strokeStyle.

clearRect(x, y, width, height)
clears the specified rectangular area, making it fully transparent.

The two color styles mentioned above can be assigned colors in the format used by CSS.

fillStyle = “#ff0000”; // set to red
fillStyle = “red”; // also sets to red using css predefined color names (see link above for all the valid names)

strokeStyle = rgb(255,0,0); // same deal, sets to red using another css color construct
strokeStyle = rgba(255,0,0, 0.5); // sets to a red with an opacity of 50%
lineWidth = 2; // how many pixels wide the stroke is, defaults to 1

The ctx variable pulled from canvas can now be used to access all the functions in the canvas api. To draw a red rectangle at coordinates 50, 50 on the canvas:

ctx.fillStyle = "red"; 
ctx.fillRect(75,75,60,60);

And before running this, adding this css in the <head> section in the HTML will show the boundaries of the canvas more clearly to help see where in the canvas objects are being drawn:

<style type="text/css">
body {margin:20px; background-color: #202020}
canvas { border: 1px solid white; }
</style>

Which creates this:

red box

Notice the the x,y coordinates of the box starts at 75, 75 which is the exact center of the 150×150 canvas. The box isn’t centered though because the x,y coordinates is where the top, left of the box starts, not the middle. Now to punch a transparent hole in the middle of that red box:

ctx.clearRect(105,150,20,20);

punch hole

and finally, draw a rectangular outline:

ctx.strokeStyle = "red";
ctx.lineWidth = 3;
ctx.strokeRect(95, 80, 20, 50);

jail

Putting it all together, the final example above was created with the following HTML:

<!DOCTYPE html>
<html lang="en">
<head>
<title>Canvas Example</title>
<style type="text/css">
body {margin:20px; background-color: #202020}
canvas { border: 1px solid white; }
</style>
</head>
<body>
<canvas id="canvas" width="150" height="150"></canvas>
<script src="draw.js">
</script>
</body>
</html>

and the following JavaScript (in draw.js):

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "red"; 
ctx.fillRect(75,75,60,60);
ctx.clearRect(105,150,20,20);
ctx.strokeStyle = "red";
ctx.lineWidth = 3; 
ctx.strokeRect(95, 80, 20, 50);

The last piece needed before cutting loose and making some cool stuff is a little helper function added to the Javascript that will return a random integer between x and y inclusively:

function randomIntBetween(min,max) {
return Math.floor(Math.random()*(max-min+1)+min);
}

Enough to get started… let’s make some art with rectangles using fills, strokes, colors and coordinates and random properties. Here’s what I built. Comments in the code should explain what was done. If you (i.e. that one guy or gal that tripped across this page while searching for blue arctic foxes) decide to make something, please post a link in the comments, which goes for all the following parts of this journey as well.

Playing with Rectangles

Left click on the canvas to generate a new pattern. Right click and save to save the image. Click Open Controls to change the parameters. (Don’t click the Rerun button that appears from CodePen unless you want to reset all the parameters.)

See the Pen Canvas 1.0 by Kentskyo (@kentskyo) on CodePen.0