JS1K

#2: the original

Source description for demo by antimatter15.

var b = document.body, c = document.getElementById("c"), t = c.getContext("2d"), cos = Math.cos, sin = Math.sin; b.style.margin = 0; c.width = innerWidth; c.height = innerHeight; var f = 200, vpX = c.width / 2, vpY = c.height / 2, p = []; var mX = 0, mY = 0; c.onmousemove = function(e){ mX = e.clientX; mY = e.clientY; } ;(c.onclick = function(eq){ p = []; var def = 'Math.PI*Math.sin(Math.sqrt(x*x+y*y))/Math.sqrt(x*x+y*y)'; var fn = new Function('x,y','return '+(eq?prompt('function',def):def)); for(var x = -10; x < 10; x+=.5){ for(var y = -10; y < 10; y+=.5){ p.push({ x: x*10, y: y*10, z: 20*fn(x,y) }) } } })(); setInterval(function(){ var aY = 1e-4 * (mX - vpX), cY = cos(aY), sY = sin(aY), aX = 1e-4 * (mY - vpY), cX = cos(aX), sX = sin(aX), point, S, z1; for(var i = p.length; i--;) { point = p[i]; z1 = point.z * cY + point.x * sY; point.x = point.x * cY - point.z * sY; point.z = z1 * cX + point.y * sX; point.y = point.y * cX - z1 * sX; S = f / (f + point.z); point._x = vpX + point.x * S; point._y = vpY + point.y * S } t.clearRect(0, 0, c.width, c.height); if(p.length){ t.strokeStyle = "rgb(40,50,20)"; t.beginPath(); t.moveTo(p[0]._x, p[0]._y); for(var l = p.length,i=1;i<l;i++){ try{ if(i % 40) t.lineTo(p[i]._x, p[i]._y); else t.moveTo(p[i]._x, p[i]._y); }catch(e){} //sometimes p[i]._x == NaN } t.stroke() } t.fillText('Click to edit equation',99,99) },0);