Personal and Professional Blog of Rich Hauck

Brownian Motion in HTML5 Canvas

January 20, 2012

Brownian Motion

Ya know, cause I couldn’t find it anywhere (Lovingly stolen from Processing documentation). View the example.

I’m hoping to convert Craig Reynolds’ Boids to JavaScript/Canvas at some point in the future, too.

window.addEventListener('load', init, false);
function init(){
	var canvas = document.getElementById("canvas");
	if (canvas.getContext('2d')){
  		main(canvas);
	} else {
    	console.log("Canvas tag is not supported");
	}
}
function main(canvas){
	var canvas = canvas;
	var ctx = canvas.getContext("2d");
	const CANVAS_WIDTH = canvas.width;
	const CANVAS_HEIGHT = canvas.height;

	var num = 10;
	var range = 200;

	var ax = [];
	var ay = [];

	for(var i = 0; i < num; i++) {
	  ax[i] = CANVAS_WIDTH/2;
	  ay[i] = CANVAS_HEIGHT/2;
	}

	setInterval(draw, 30);

	function draw(){
		// Shift all elements 1 place to the left
		  for(var i = 1; i < num; i++) {
		    ax[i-1] = ax[i];
		    ay[i-1] = ay[i];
		  }
		  // Put a new value at the end of the array
		  var r2x = range*2;
		  ax[num-1] += (Math.random()*r2x)-range;
		  ay[num-1] += (Math.random()*r2x)-range;

		  // Constrain all povars to the screen
		  ax[num-1] = constrain(ax[num-1], 0, CANVAS_WIDTH);
		  ay[num-1] = constrain(ay[num-1], 0, CANVAS_HEIGHT);

		  // Draw a line connecting the povars
		  for(var i = 1; i < num; i++) {

			var alpha = i/num;
			ctx.globalAlpha = i/num;

			ctx.moveTo(ax[i-1], ay[i-1]);
			ctx.lineTo(ax[i], ay[i]);
			ctx.stroke();
		  }
	}
	function constrain(val, min, max){
		if(val > max){
			val = max;
		}else if(val < min){
			val = min;
		}
		return val;
	}
}
Categories: canvas, HTML5

Working with HTML5 Range Input

January 17, 2012

View Example

I felt compelled to post this HTML5 range input example because I couldn’t find code online that didn’t rely on JQuery to output a value (not that I have anything against it, just that it can be overkill for simple things like this).

The code below outputs the value of the range to a nearby <span>. I created a “showOutput” function to make it easier to use with multiple inputs.

window.addEventListener('load', initSlider, false);
/**
* Initializes sliders
*/
function initSlider(){
	// get range input
	var myRange = document.getElementById("myRange");
	myRange.addEventListener('change', function(){showOutput(myRange, "rangeOuput")}, false);
	document.getElementById("rangeOuput").innerHTML = rangeOuput.value;

	// call range input on window init to display initial value
	showOutput(myRange, "rangeOuput");
	/**
	* Displays output to text fields.
	* @param slider		id of range input
	* @param field		id of span to write value.
	*/
	function showOutput(slider, field){
		document.getElementById(field).innerHTML = slider.value;
	}
}
Categories: HTML5, javascript

Revisiting Interactive Media

January 16, 2012
fibonacci

Playing around with the Fibonacci number in Canvas. Click image for example. Code below.

I recently read a CNN op-ed piece by my former instructor, Doug Rushkoff, on how coding should be taught in every school as a way to be more competitive in the global industry. I couldn’t agree more.

For the past two years I’ve taught an Interactive Media course at Harrisburg Area Community College that has traditionally been taught in Adobe Flash. This semester, I decided to revisit the medium in which to teach interactive media, especially now that web-based Flash is being replaced with web standards technology like HTML, CSS, and JavaScript.

I haven’t completely replaced Flash in the course, as it remains a valuable tool for complex animation, video, and games. I have, however, decided to begin with the fundamentals of programming, and feel that the Flash IDE has too many distractions to serve as the starting medium.

I gave a lot of thought towards Processing, provided it’s easy-to-approach IDE, its large community, and its excellent documentation. In the end, though, I decided on HTML5 Canvas, as my students will likely end up using javascript instead of Java.

To a more selfish end, it’s forced me to better grasp canvas and JavaScript. I purposely chose a medium I wanted to learn, as I’m already comfortable with Flash and doubt I will be revisiting Java.

I’m going to try and start posting more code, such as this for the Fibonacci example:

window.addEventListener('load', init, false);
var canvas;
/**
* Detects for context 2d
*/
function init(){
	canvas = document.getElementById("myCanvas");
	if (canvas.getContext('2d')){
  		main(canvas);
		initSliders();
	} else {
    	console.log("Canvas not supported");
	}
}
/**
* Initializes sliders
*/
function initSliders(){
	var radRange = document.getElementById("radRange");
	radRange.addEventListener('change', function(){showOutput(radRange, "rangeOuput")}, false);
	document.getElementById("rangeOuput").innerHTML = radRange.value;

	var distRange = document.getElementById("distRange");
	distRange.addEventListener('change',  function(){showOutput(distRange, "distOuput")}, false);
	document.getElementById("distOuput").innerHTML = distRange.value;

	/**
	* Displays output to text fields.
	* @param slider		id of range input
	* @param field		id of span to write value.
	*/
	function showOutput(slider, field){
		document.getElementById(field).innerHTML = slider.value;
	}
}
/**
* Main
* @param canvas target canvas
*/
function main(canvas){
	var ctx = canvas.getContext("2d");

	var max = 200; 						// number of items on screen
	var i = 0; 							// initialize for counter
	const fib = 1/1.618033989;			// Fibonacci Sequence
	var radius = 0; 					// initial radius
	var lastInputRadius;				// remembers previous state to determine if positioning needs changed
	var lastInputDistance;				// remembers previous state to determine if positioning needs changed

	var circles = [];		 			// Create Array to hold items

	const CANVAS_RIGHT = canvas.width;
	const CANVAS_BOTTOM = canvas.height;

	var interval = setInterval(draw, 30);

	/**
	* Draws pattern to screen
	*/
	function draw() {
		var inputRadius = document.getElementById("rangeOuput").innerHTML;
		var inputDistance = document.getElementById("distOuput").innerHTML;
		if(i < max){
			// create shape
			radius += inputRadius*fib;
			lastInputRadius = inputRadius;
			lastInputDistance = inputDistance;
		    var dist = i*inputDistance; //represents distance from object
		    var x = Math.cos(radius*Math.PI/180)*dist + CANVAS_RIGHT/2;
		    var y = Math.sin(radius*Math.PI/180)*dist + CANVAS_BOTTOM/2;
			var hex = rgbToHex(255-i,0,i);
		    circles[i] = new Circle(ctx, x, y, (i/max)*100, hex);
		    i++;
		}else{
			// if input has changed, reposition shape
			if(lastInputRadius != inputRadius || lastInputDistance != inputDistance){
				radius += inputRadius*fib;
				clear();
				for(var j = 0; j < max; j++){
					radius += inputRadius*fib;
				    var dist = j*inputDistance; //represents distance from object
				    var x = Math.cos(radius*Math.PI/180)*dist + CANVAS_RIGHT/2;
				    var y = Math.sin(radius*Math.PI/180)*dist + CANVAS_BOTTOM/2;
					var hex = rgbToHex(255-j,0,j);
					circles[j].render(x, y, (j/max)*100, hex);
				}
			}
		}
		lastInputRadius = inputRadius;
		lastInputDistance = inputDistance;
	}
	/**
	* Draws circle.
	*/
	function Circle(ctx, x, y, r, hex){
		this.ctx = ctx;
		this.centerX = x;
		this.centerY = y;
		this.radius = r;

		this.render = function render(x, y, r, hex){
			this.centerX = x;
			this.centerY = y;
			this.radius = r;

			this.ctx.beginPath();
			this.ctx.arc(this.centerX, this.centerY, this.radius, 0, 2*Math.PI, false);
			this.ctx.fillStyle = hex;
			this.ctx.fill();
			this.ctx.lineWidth = 2;
			this.ctx.strokeStyle = "black";
			this.ctx.stroke();
		}
		this.render(this.centerX, this.centerY, this.radius, hex);
	}
	/**
	* Converts RGB values to hexidecimal
	* @param r 0-255 red value
	* @param g 0-255 green value
	* @param b 0-255 blue value
	*/
	function rgbToHex(r, g, b) {
		/**
		* Converts numeric value to base-16
		* @param c		target value
		*/
		function componentToHex(c) {
		    var hex = c.toString(16);
		    return hex.length == 1 ? "0" + hex : hex;
		}

	    return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
	}
	/**
	* Clears the canvas
	*/
	function clear(){
		ctx.clearRect(0, 0, CANVAS_RIGHT, CANVAS_BOTTOM);
	}
}

It’s been difficult not having a definitive API documentation like ActionScript and Processing have. The best I’ve found so far has been HTML5 Canvas Tutorials accompanied by a lot of O’Reilly JavaScript books. Coming from an ActionScript background, I’m still wrapping my head on how every function is an object, and how privatization, and event listening isn’t quite so baked in. I’m know the code above could be optimized more–eliminating globals, calculating x and y-positions once in draw(), etc., but it’s just a sketch.

I haven’t quite figured out how to structure my experiments on this blog, but my goal this year is posting more content, and spending less time examining distractions and vices.

Categories: canvas, HTML5, webdesign

BarcampHbg4

January 8, 2012

Time for my obligatory post–BarCampHbg4 is coming Saturday, March 31, 2012! It’s hard to believe this will mark the event’s fourth year…It’s nice to see the attendance gets bigger every year. This year, we’re shooting for at least 200 people, and with over 100 signups and 3 months to go, I think we’re in pretty good shape. If you’re interested in talking technology, social media, education, or mobile, you should definitely register.

Baseball 2011

January 4, 2012

I enjoy attending baseball games. It forces me to block out my schedule, not think about work, and spend time with friends.

In 2007 and 2008, I spent a lot of time at Yankee Stadium cheering on the Yankees. It wasn’t difficult, considering I lived near the stadium, had generous season ticket-holding friends in New York, and fell out of following baseball after 1994 strike (it didn’t hurt that my favorite Orioles pitcher–Mussina, changed to pinstripes, either). When I returned to Central PA at the end of 2008, I sort of went through a withdrawal of not attending baseball games. I tried traveling to the Bronx in 2009, but the commute was brutal (sometimes getting home at 4 a.m. or scrambling for a couch in the city) and costly (sometimes paying up to $60 for parking).

Last year, I bought a partial Orioles season ticket plan and rediscovered my roots, so to say (I briefly went to college in Baltimore and grew up an Orioles fan). My first game was a bit surreal, but I can safely say I’ve reverted my allegiance back to my current “home” team. The shorter commute has also proved to be the perfect amount of time to hang out with friends without feeling the exhaustion of a long trip.

I’ve started a tradition with one of my brother-in-laws of visiting a new ballpark each year (this year was PNC in Pittsburgh). I’ve also started a tradition of getting a picture with those I attend baseball games with; I’m posting what I have of 2010 and 2011 (above) online.

I renewed my Orioles seats for 2012, and this year hope to drag a whole new set of people down to the ballpark (possibly including my wife, who isn’t a baseball fan but humors me). If we’re friends and you harbor some secret interest for going to games, you should let me know :)

Christmas Card 2011

December 23, 2011


Christmas Card 2011

Well, I wrapped up this year’s Christmas card. I actually started with some concepts on paper–before inevitably moving to my iPad and Cintiq. I had another concept I liked better, but that’ll be for next year.

I still prefer sending out my custom-drawn cards, but am getting slight pressure from the Mrs. to do one of those cheesy, glossy postcards with canned messages–just so people can actually see our kids. I suppose I’ll cave in once those photography studios offer cards like this.

In the meanwhile, if there’s any friends of mine that didn’t get one of these cards but want on the list, send me your address. :)

 

Categories: art
Tags: , ,

I’m a sucker for good candy packaging.

December 20, 2011


I picked up this little guy from Economy Candy the other day. This Bob-omb’s top unscrews to contain a dipper with cherry-flavored sugar, but let’s be honest, I didn’t buy it for the candy.

Categories: food and drink, NYC

Bye Bye Facebook

December 19, 2011

Last week I deactivated my Facebook account.

I suppose I ought to apologize as, from what I’ve heard, it’s proper etiquette to notify friends that you’re closing your page down. I had a surprised wife who went from being “married to Richard Hauck” to just being “married”, got a text or two, as well as a phone call from a friend that thought I’d silently unfriended him out of anger (a childish tactic I hope I never execute). For the most part, my disappearance has gone unnoticed.

Apparently, I’m not alone, according to this NY Times article.

I didn’t delete my account because I’m assuming that I’ll inevitably reactivate it–either for a client job that requires it or from just plain missing it. Having no access has already made it difficult to confirm mailing addresses and access Spotify.

Why’d I delete it? It wasn’t for security reasons (though perhaps it should have been, considering how Facebook cookies infinitely track you), rather I tend to think I’ve ruined Facebook for myself, as my wall’s been overrun by acquaintances and high school friends I haven’t seen since I graduated. My Google+ account strangely started becoming Facebook to my Facebook account, as the latter seemed to have transformed into MySpace.

I could unsubscribe from these folks, but I also don’t like how Facebook has become the defacto use of the web. Have pictures to post? Don’t use Flickr or Instagram, use Facebook! Have a party to send invites to? Create a Facebook event! Need to log in? Don’t use OpenID directly, use your Facebook account!

So far, I don’t miss it. I might start blogging more, as well as try out other accounts, such as Path and Diaspora. Or, I might become more social by not using these services as much. Time will tell.

Biking the Abandoned Turnpike

October 20, 2011

I feel somewhat guilty for bringing more attention this rather hidden gem, but I found it to be a photographer’s paradise.

If you’re unfamiliar with the abandoned turnpike, it’s a 13-mile stretch of highway off of Breezewood (between Harrisburg and Pittsburgh) that was active from 1940 to 1968. The turnpike commission bypassed this section to alleviate tunnel traffic. As a result, the Sideling Hill and Rays Hill tunnels were abandoned, and a travel plaza was leveled.

The property was sold in 2001 to the Southern Alleghenies Conservancy, and has since been passed along to the Friends of Pike 2 Bike.

The land is free to bike on, but at one’s own risk. I rode with a group of roughly 12 people, and after making the trek, I would discourage anyone from going out there on their own.

Kudos to floor9.com for organizing this trip.

Abandoned Turnpike

Only 8 miles of the 13 miles are accessible, as each end remains the private property of the turnpike commission. As you can see, the condition of the road is slowly deteriorating.

Rays Hill Tunnel

The entryway to the Rays Hill Tunnel. The doors to these tunnels were either soldered shut or missing.

The Sideling Hill Tunnel is roughly 1.3 miles long and the Rays Hill Tunnel is ~0.5 miles long. Bike headlights are a must, especially with Sideling Hill, as you can't see the end of the opposite side.

Sideling Hill

We took the steps up to the top of the tunnel where we got to see the huge exhaust fans. These fans were found above each end of the tunnel. Sideling Hill's fans were painted with graffiti. The entrance way (center) leads to an access tunnel above the road.

Above the tunnel

Above each tunnel runs an equally long access tunnel. Support beams run across the center, and a rusted track remains for what could possibly have been a rail car. This portion was a bit treacherous, as, despite what this long exposure displays, the hall was pitch black, and large holes in the floor remain where lights once hung.

In the Tunnel

Here's a shot from inside the tunnel, looking east. Some of the square "windows" showed the bedrock. From what I've been told, these tunnels originated as railway tunnels, and the current tunnel doesn't actually touch the underlying rock.

Exhaust Fans

Here are the Rays Hill Tunnel exhaust fans.

These fans showed quite a bit of rust, but not much graffiti. This was probably due to the fact that the staircase had rusted and collapsed. Some of us crawled through the top and worked our way down.

End

At the end of the 8-mile stretch is PA Turnpike-owned private property. Apparently, a bridge spanned the gap to the east connection, but was torn down in 2005 since it was no longer structually sound.

Categories: travel
Tags: ,

Woodstock ’99

October 14, 2011

Found this in a dresser drawer at my parents’ house. I wonder how many folks still have one of these intact…

Categories: travel

About Me

Rich HauckI'm a designer, developer, and teacher based in Harrisburg, Pa. I run Hauck Interactive, Inc.




Archives