JavaScript Day 25: More Art

Mar 25 2011 Published by under JavaScript

I think I’ve covered most of the large technical aspects of JavaScript and canvas that I will be covering for the month. I’ll probably finish up with a bunch of random experiments utilizing all the stuff we’ve covered up till now. But who knows, I might come up with another topic or two as we go along.

Today, we’ll create a kind of artsy network/node diagram that looks like this:

Click to view full size.

Here’s the code:

$(function () {
var i, canvas, context, points = [], width, height;

canvas = $(“#canvas”)[0];
context = canvas.getContext(“2d”);
width = canvas.width;
height = canvas.height;
context.strokeStyle = “rgba(0, 0, 0, 0.2)”;

setInterval(function() {
var p0, p1, dx, dy, dist, max = 150;
p0 = {x:Math.random() * width, y:Math.random() * height};
for(i = 0; i < points.length; i += 1) { p1 = points[i]; dx = p1.x - p0.x; dy = p1.y - p0.y; dist = Math.sqrt(dx * dx + dy * dy); console.log(dist); if(dist < max) { context.beginPath(); context.lineWidth = 1.0 - dist / max; context.moveTo(p0.x, p0.y); context.lineTo(p1.x, p1.y); context.stroke(); } } points.push(p0); }, 1000/24); });[/php] We start out with an array called points. On each frame, we create a random x, y point. Then we loop through the existing points in the array and find out the distance from each one to the new one. If it is less than a maximum distance, we'll draw a line between the two. The trick to making it look cool is to first start out with a very low alpha on the stroke style: context.strokeStyle = "rgba(0, 0, 0, 0.2)"; And then to vary the line width according to the length of the line with this formula: context.lineWidth = 1.0 - dist / max; This is in a conditional which ensures that dist is less than max. So dist / max will range somewhere between 0 and 1. We subtract that value from 1.0. This means that the further the points are from each other, the thinner the line will be, and as they get closer together, the line width approaches 1. You can see it working here, but note that it is completely unoptimized and will definitely crank your CPU. The longer it runs, the more points it will need to iterate through on each frame, so it's just going to get worse and worse. Don't let it run too long!

6 responses so far. Comments will be closed after post is one year old.

  • √ėyvind Nordhagen says:

    Hi, Keith. I’ve been following this series of JS posts and I’m wondering about something I see both in your code and often elsewhere as well. In JS people seem to be inlining functions and objects quite a lot. Since it usually isn’t required I take it that this just seems to be an agreed upon convension among JS devs, whereas in AS we use function references instead. To me the inlining feels like going backwards. Not because it’s just less like ActionScript, but because it makes the programming style more procedural instead of modular.

    What’s your take on this?

    • keith says:

      Yeah it does seem to be a sort of convention. I guess where you say inlining isn’t required and why don’t you use a reference, JS devs would say, a ref isn’t required, why don’t you just inline it?

      Of course you can do things more modularly, and for larger, more complex projects I probably would, but for small snippets like this, it works out well and I’m getting used to it.

  • Evan Mullins says:

    very cool.

    I’m still thinking about something you referenced earlier in the series about instantiating all vars in one line at eh beginning of the code. I see that here, and it makes sense, but how come for example the max var is no instantiated globally? Is it just the scope? Try to put everything in the narrowest scope possible? I know you said this isn’t optimized at all, but I wonder if re-instantiating the max var every “frame” is more of a load than having one globally that persists. I’m not trying to nitpick, just wondering if there is real thought into where max’s scope is.

    ps- I’m starting to dread the end of the month now. =)

    • keith says:

      Good point Evan. I think the rule about one line vars is definitely scope (function) related. It’s trivial in this example, but you definitely wouldn’t want to define all the vars for a many-functioned program in one line. Each function would have its own vars.

      In terms of the performance, I would imagine that the function and its vars are defined a single time, not each time it is run, but that could depend on the particular browser/platform implementation. Don’t know.

  • […] on Canvas JavaScript Day 22: Transformation JavaScript Day 23: Shadows JavaScript Day 24: Curves JavaScript Day 25: More Art JavaScript Day 26: Mouse Part I JavaScript Day 27: Mouse Part II JavaScript Day 28: Creating a UI […]