Christmas JS1k

December 29, 2010

Gifted the benefit of R&D time at work, at the end of 2010 I submitted an entry to the Christmas JS1k contest along with my fellow POPsters. I got to geek out and spend work time creating something cutting-edge that I’m pretty proud of: a canvas drawing app!

My goals were to:

  • Learn enough native JS to complete an entry(!)
  • Use canvas
  • Keep usability in mind since it tends to go out the window when shaving off bytes: cursors, tip text, etc.

To see what I ended up with (as well as a super fancy jQuery version that was my starting point), you can play with a demo here.

What is JS1k, you ask? From the source: “the object of this competition is to create a cool JavaScript “application” no larger than 1k. Starting out as a joke, the first version ended with a serious amount of submissions, prizes and quality.”

View my uncompressed JS1k entry


<script type="text/javascript">
	var c = document.getElementsByTagName('canvas')[0];
	var b = document.body;
	var a = c.getContext('2d');
	</script> 
	<script type="text/javascript">
	d=document;
	
	h=d.createElement('h1');
	h.innerHTML='Draw.';
	b.insertBefore(h, c);
	
	// context abbreviation loop
	for($ in a){
		a[$[0]+($[6]||$[2])]=a[$];
	}
	
	// commonly used integers
	x=150;
	y=120;
	
	c.width=c.height=x*2;
	k='background:#';
	z=c.style;
	z.cssText=k+"416012";
	
	// pen color array
	A=['000','0e943a','C0C0C0','C5B358'];
	co = '#'+A[0];
	
	//create color squares
	for(i=0;i<4;i++){
	  sqr(A[i]);
	}
	// not overlapping circle
	oLp = 0;
	// not drawing
	drw = 0;
	
	onmousemove=function(e){
	
		// get mouse/canvas properties
		gTs(e,c)
		
		// mouse intersects circle
		if(dI(eX-oL, eY-oT)){
			
			z.cursor='crosshair';
			oLp = 1;
			// if the mouse is down, leave a mark
			if (drw == 1) {
			with(a){
	                ln(eX-oL, eY-oT); // lineTo
	                strokeStyle = co;
	                sr() // stroke
	            }
            }
		}
		// mouse off circle
		else {
			z.cursor='default';
			oLp = 0;
			drw = 0
		}
	};
    onmouseup=function(){ drw = 0}
    onmousedown=function(e){
    	// if overlapping
		if(oLp) {
			gTs(e,e.target)
			drw = 1;
			with(a){
				ba(); // beginPath
				lineWidth=3;
				mv(eX-oL, eY-oT) // moveTo
			}
        }
	}
	// get target values
	function gTs(e,t){
		eX=e.pageX;
		eY=e.pageY;
		oL=t.offsetLeft;
		oT=t.offsetTop;
	}
	// create square: k='background:#', v=color from array
	function sqr(v){
		n=d.createElement('a');
		n.id=v;
		n.style.cssText=k + v +';cursor:pointer;height:15px;float:left;margin:0 8px 0 0;width:15px';
		n.onclick=function(e){co='#'+e.target.id}
		b.appendChild(n)
	}
	// does intersect: a=pageX, b=pageY, x=circleX/circleY, y=circleRadius
	function dI(a,b) {
	    f = a-x;
	    g = b-x;
	    return f*f+g*g <= y*y
	}
	// create sphere
	with(a){
		g=cR(x,y,0,x,y,200); // createRadialGradient
		g.addColorStop(0,'#f00');
		g.addColorStop(1,'#600');
		ba(); // beginPath
		fillStyle=g;
		ac(x, x, y, 0, Math.PI*2,false); // arc
		ca(); // closePath
		fl() // fill
	}
	</script>