March Madness 9 – Paint
Here’s a simple paint program I made using canvas. It’s a pretty blatent ripoff of another one that a friend showed me today, but unfortunately I don’t have the URL handy. (Sorry, I’ll update in the morning!) The framework makes it pretty simple for you to add your own tools. Click on for source.
Update: Harmony was the inspiration I was looking for!
JPLT.Class.create("JPLT.PaintTool", JPLT.Object, function() { this.isPainting = false; this.x = 0; this.y = 0; this.d = 0; this.a = 0; this.isPainting = false; }, { mouseMoved: function(e) { var x2 = e.clientX; var y2 = e.clientY; this.oldx = this.x; this.oldy = this.y; this.dy = y2-this.y; this.dx = x2-this.x; this.d = Math.sqrt(Math.pow(this.dx,2)+Math.pow(this.dy,2)); this.a = Math.atan2(this.dy,this.dx); this.x = x2; this.y = y2; }, mousePressed: function() { this.isPainting = true; }, mouseReleased: function() { this.isPainting = false; }, paint: function(ctx) { } } ); JPLT.Class.create("JPLT.PaintTool.InkBlob", JPLT.PaintTool, function() { this.superConstruct() this.radius = 1; }, { mouseMoved:function(e) { this.superCall("mouseMoved",e); if (this.radius > 1) { this.radius = Math.max(this.radius-this.d/5,1); } }, mouseReleased:function(e) { this.superCall("mouseReleased",e); this.radius = 1; }, paint: function(ctx) { if (this.isPainting) { ctx.fillStyle = "rgba(0,0,0,0.3)"; ctx.beginPath(); ctx.arc(this.x, this.y, this.radius, 0, 2*Math.PI, false); ctx.fill(); this.radius += 0.5; } } } ); JPLT.Class.create("JPLT.PaintTool.Ribbon", JPLT.PaintTool, function() { this.superConstruct(); }, { paint: function(ctx) { if (this.isPainting) { ctx.save(); ctx.strokeStyle = "rgba(0,0,0,0.3)"; ctx.translate(this.x,this.y); ctx.rotate(this.a); ctx.beginPath(); ctx.moveTo(-10,-10); ctx.lineTo(10,10); ctx.stroke(); ctx.restore(); } } } ); JPLT.Class.create("JPLT.PaintTool.Slinky", JPLT.PaintTool, function() { this.superConstruct(); }, { paint:function(ctx) { if (this.isPainting) { ctx.save(); ctx.strokeStyle = "rgba(0,0,0,0.3)"; ctx.beginPath(); ctx.arc(this.x,this.y,10,this.a,this.a+Math.PI,true); ctx.stroke(); ctx.restore(); } } } ); JPLT.Class.create("JPLT.PaintTool.Line", JPLT.PaintTool, function() { this.superConstruct(); }, { paint:function(ctx) { if (this.isPainting) { ctx.save(); ctx.strokeStyle = "rgba(0,0,0,0.3)"; ctx.beginPath(); ctx.moveTo(this.x-this.dx,this.y-this.dy); ctx.lineTo(this.x,this.y); ctx.stroke(); ctx.restore(); } } } ); JPLT.Class.create("JPLT.Paint", JPLT.Object, function() { this.width = window.innerWidth; this.height = window.innerHeight; this.currentTool = new JPLT.PaintTool.InkBlob(); this.createElement(); this.run(); }, { tools: { 'inkblob': new JPLT.PaintTool.InkBlob(), 'ribbon': new JPLT.PaintTool.Ribbon(), 'slinky': new JPLT.PaintTool.Slinky(), 'line': new JPLT.PaintTool.Line() }, createElement: function() { var body = document.documentElement || document.body; this.element = document.createElement("canvas"); this.element.width = this.width; this.element.height = this.height; this.element.style.position = "absolute"; this.element.addEventListener("mousemove", this.delegate(this.mouseMoved), true); this.element.addEventListener("mousedown", this.delegate(this.mousePressed), true); this.element.addEventListener("mouseup", this.delegate(this.mouseReleased), true); body.appendChild(this.element); var div = document.createElement("div"); div.style.textAlign = "center"; div.style.position = "absolute"; div.style.zIndex = 1; div.style.width = this.width; var select = document.createElement("select"); select.addEventListener("change", this.delegate(this.changeTool), true); for (var tool in this.tools) { var option = document.createElement("option"); option.value = tool; option.text = tool; select.add(option,null); } div.appendChild(select); var clearButton = document.createElement("button"); clearButton.innerHTML = "clear"; clearButton.addEventListener("click", this.delegate(this.clear), true); div.appendChild(clearButton); var saveButton = document.createElement("button"); saveButton.innerHTML = "save"; saveButton.addEventListener("click", this.delegate(this.save), true); div.appendChild(saveButton); body.appendChild(div); }, mouseMoved: function(e) { this.currentTool.mouseMoved(e); }, mousePressed: function(e) { this.currentTool.mousePressed(e); }, mouseReleased: function(e) { this.currentTool.mouseReleased(e); }, context: function() { return this.element.getContext("2d"); }, run: function() { if (!this.timer) { this.timer = window.setInterval(this.delegate(this.paint), this.delay); } }, stop: function() { window.clearInterval(this.timer); this.timer = null; }, changeTool: function(e) { var newTool = e.target.value; this.log("Changed tool to " + newTool); this.currentTool = this.tools[newTool]; }, clear: function() { var ctx = this.context(); ctx.clearRect(0,0,this.width,this.height); }, save: function() { window.open(this.element.toDataURL()); }, paint: function() { try { var ctx = this.context(); this.currentTool.paint(ctx); } catch (e) { this.stop(); throw(e); } } } );
-
simondorfman
-
Justin Day
