From 38287e2a2476d43bc08d72f65e17ed1e7fed9309 Mon Sep 17 00:00:00 2001 From: Luis Leiva Date: Sat, 7 Jul 2012 19:07:58 +0200 Subject: [PATCH] Initial commit. --- jquery.sketchable.js | 323 +++++++++++++++++++++++++++++++++ jquery.sketchable.min.js | 5 + jsketch.js | 383 +++++++++++++++++++++++++++++++++++++++ jsketch.min.js | 5 + 4 files changed, 716 insertions(+) create mode 100644 jquery.sketchable.js create mode 100644 jquery.sketchable.min.js create mode 100644 jsketch.js create mode 100644 jsketch.min.js diff --git a/jquery.sketchable.js b/jquery.sketchable.js new file mode 100644 index 0000000..11a2b0c --- /dev/null +++ b/jquery.sketchable.js @@ -0,0 +1,323 @@ +/*! + * jQuery sketchable 1.3 | Luis A. Leiva | MIT license + * This is a jQuery plugin built on top of jSketch drawing class. + */ +/** + * @name $ + * @class + * See the jQuery library for full details. + * This just documents the method that is added to jQuery by this plugin. + */ +/** + * @name $.fn + * @class + * See the jQuery library for full details. + * This just documents the method that is added to jQuery by this plugin. + */ +;(function($){ + // config options + namespace ID + var options, _ns = "sketchable"; + /** + * Note: This is NOT a constructor actually, but a series of methods to be + * called from the plugin. + * @name methods + * @class + * Plugin API. + */ + var methods = { + /** + * Initializes the selected jQuery objects. + * @param {Object} opts plugin configuration (see defaults) + * @return jQuery + * @name init + * @ignore + * @methodOf methods + * @example $(selector).sketchable(); + */ + init: function(opts) { + // options will be available for all plugin methods + options = $.extend({}, $.fn.sketchable.defaults, opts); + return this.each(function() { + var elem = $(this), data = elem.data(_ns); + // first-time checks + if (!data) { + // TODO: add more drawing properties (and set them configurable) + var sketch = new jSketch(this, { + fillStyle: options.graphics.fillStyle, + strokeStyle: options.graphics.strokeStyle, + lineWidth: options.graphics.lineWidth, + })//.background(options.graphics.background); // let user decide... + + elem.data(_ns, { + strokes: [], // mouse strokes + coords: [], // a single stroke + canvas: sketch + }); + + if (options.interactive) { + elem.bind("mousedown", mousedownHandler); + elem.bind("mouseup", mouseupHandler); + elem.bind("mousemove", mousemoveHandler); + elem.bind("touchstart", touchHandler); + elem.bind("touchend", touchHandler); + elem.bind("touchmove", touchHandler); + // fix Chrome "bug" + this.onselectstart = function(){ return false }; + } + } + if (typeof options.events.create === 'function') { + options.events.create(elem, elem.data(_ns)); + } + }); + }, + /** + * Gets/Sets drawing data strokes sequence. + * @param Array arr data strokes: multidimensional array of [x,y,status]'s; status = 0 (pen down) or 1 (pen up) + * @return Strokes object on get, jQuery on set (with the new data attached) + * @name strokes + * @methodOf methods + * @example + * $(selector).sketchable('strokes'); + * $(selector).sketchable('strokes', [ [arr1], ..., [arrN] ]); + */ + strokes: function(arr) { + if (arr) { // setter + return this.each(function() { + var elem = $(this), data = elem.data(_ns); + data.strokes = arr; + }); + } else { // getter + var data = $(this).data(_ns); + + return data.strokes; + } + }, + /** + * Allows low-level manipulation of the sketchable canvas. + * @param Object callback function, invoked with 2 arguments: + * * elem: jQuery element + * * data: canvas (DOM element) + * @return jQuery + * @name handler + * @methodOf methods + * @example + * $(selector).sketchable('handler', function(elem, data){ + * // do something with elem or data + * }); + */ + handler: function(callback) { + return this.each(function() { + var elem = $(this), data = elem.data(_ns); + callback(elem, data); + }); + }, + /** + * Clears canvas (and strokes data). + * @return jQuery + * @name clear + * @methodOf methods + * @example $(selector).sketchable('clear'); + */ + clear: function() { + return this.each(function() { + var elem = $(this), data = elem.data(_ns); + data.canvas.clear(); + data.strokes = []; + if (typeof options.events.clear === 'function') { + options.events.clear(elem, data); + } + }); + }, + /** + * Reinitializes a sketchable canvas with given opts. + * @param Object opts configuration options + * @return jQuery + * @name reset + * @methodOf methods + * @example + * $(selector).sketchable('reset'); + * $(selector).sketchable('reset', {interactive:false}); + */ + reset: function(opts) { + return this.each(function(){ + var elem = $(this), data = elem.data(_ns); + elem.sketchable('destroy').sketchable(opts); + if (typeof options.events.reset === 'function') { + options.events.reset(elem, data); + } + }); + }, + /** + * Destroys sketchable canvas (and strokes data). + * @return jQuery + * @name destroy + * @methodOf methods + * @example $(selector).sketchable('destroy'); + */ + destroy: function() { + return this.each(function(){ + var elem = $(this), data = elem.data(_ns); + if (options.interactive) { + elem.unbind("mousedown", mousedownHandler); + elem.unbind("mouseup", mouseupHandler); + elem.unbind("mousemove", mousemoveHandler); + elem.unbind("touchstart", touchHandler); + elem.unbind("touchend", touchHandler); + elem.unbind("touchmove", touchHandler); + } + elem.removeData(_ns)//.remove(); + if (typeof options.events.destroy === 'function') { + options.events.destroy(elem, data); + } + }); + } + + }; + + /** + * Creates a new jQuery.sketchable object. + * @param {String|Object} method name of the method to invoke, + * or a configuration object. + * @returns jQuery + * @class + * @version 1.3 + * @example + * $(selector).sketchable(); + * $(selector).sketchable({interactive:false}); + */ + $.fn.sketchable = function(method) { + if (methods[method]) { + return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); + } else if (typeof method === 'object' || !method) { + return methods.init.apply(this, arguments); + } else { + $.error('Method '+ method +' does not exist on jQuery.sketchable'); + } + return this; + }; + + /** + * Default configuration (publicly modifiable). + * Note that on[ยทยทยท] callbacks are triggered only if interactive == true. + * @name defaults + * @default + * @memberOf $.fn.sketchable + * @example + * $(selector).sketchable({ + * interactive: true, + * events: { + * create: function(elem,data){}, + * clear: function(elem,data){}, + * destroy: function(elem,data){}, + * mouseDown: function(evt){}, + * mouseMove: function(evt){}, + * mouseUp: function(evt){}, + * }, + * graphics: { + * lineWidth: 2, + * strokeStyle: '#F0F', + * fillStyle: '#F0F', + * lineCap: "round", + * lineJoin: "round", + * miterLimit: 10 + * } + * }); + */ + $.fn.sketchable.defaults = { + // if interactive is set to true, you can: + // * draw on canvas via mouse/pen/touch input + // * assign callbacks to onMouseDown(evt), onMouseMove(evt), onMouseUp(evt) + interactive: true, + events: { + // create: function(elem,data){}, + // clear: function(elem,data){}, + // destroy: function(elem,data){}, + // mouseDown: function(evt){}, + // mouseMove: function(evt){}, + // mouseUp: function(evt){}, + }, + // TODO: add more jSketch config options + graphics: { + fillStyle: '#F0F', + strokeStyle: '#F0F', + lineWidth: 2 + //lineCap: + //lineJoin: + //miterLimit: + } + }; + + + + // main drawing callbacks if interactive is set to true ---------------------- + + function getMousePos(e) { + var elem = $(e.target), pos = elem.offset(); + return { + x: e.pageX - pos.left, + y: e.pageY - pos.top + } + }; + + function mousemoveHandler(e) { + var elem = $(e.target), data = elem.data(_ns); + if (!data.canvas.isDrawing) return; + var p = getMousePos(e); + data.canvas.lineTo(p.x, p.y); + //data.coords.push({ x:p.x, y:p.y, type:0 }); + data.coords.push([ p.x, p.y, 0 ]); + if (typeof options.events.mouseMove === 'function') { + options.events.mouseMove(e); + } + }; + + function mousedownHandler(e) { + var elem = $(e.target), data = elem.data(_ns); + data.canvas.isDrawing = true; + var p = getMousePos(e); + data.canvas.beginPath(); + // mark visually 1st point of stroke + data.canvas.fillCircle(p.x,p.y,options.graphics.lineWidth); + //data.coords.push({ x:p.x, y:p.y, type:1 }); + data.coords.push([ p.x, p.y, 1 ]); + if (typeof options.events.mouseDown === 'function') { + options.events.mouseDown(e); + } + }; + + function mouseupHandler(e) { + var elem = $(e.target), data = elem.data(_ns); + data.canvas.isDrawing = false; + data.canvas.closePath(); + data.strokes.push(data.coords); + data.coords = []; + if (typeof options.events.mouseUp === 'function') { + options.events.mouseUp(e); + } + }; + + function touchHandler(e) { + e.preventDefault(); + var elem = $(e.target); + var touch = e.originalEvent.changedTouches[0]; + touch.type = e.type; + // remove (emulated) mouse events on mobile devices + switch(e.type) { + case "touchstart": + elem.unbind(e.type, mousedownHandler); + mousedownHandler(touch); + break; + case "touchmove": + elem.unbind(e.type, mousemoveHandler); + mousemoveHandler(touch); + break; + case "touchend": + elem.unbind(e.type, mouseupHandler); + mouseupHandler(touch); + break; + default: + return; + } + }; + +})(jQuery); diff --git a/jquery.sketchable.min.js b/jquery.sketchable.min.js new file mode 100644 index 0000000..93044f7 --- /dev/null +++ b/jquery.sketchable.min.js @@ -0,0 +1,5 @@ +/* + * jQuery sketchable 1.3 | Luis A. Leiva | MIT license + * This is a jQuery plugin built on top of jSketch drawing class. + */ +(function(f){var i,d="sketchable";var a={init:function(j){i=f.extend({},f.fn.sketchable.defaults,j);return this.each(function(){var k=f(this),l=k.data(d);if(!l){var m=new jSketch(this,{fillStyle:i.graphics.fillStyle,strokeStyle:i.graphics.strokeStyle,lineWidth:i.graphics.lineWidth,});k.data(d,{strokes:[],coords:[],canvas:m});if(i.interactive){k.bind("mousedown",g);k.bind("mouseup",h);k.bind("mousemove",e);k.bind("touchstart",c);k.bind("touchend",c);k.bind("touchmove",c);this.onselectstart=function(){return false}}}if(typeof i.events.create==="function"){i.events.create(k,k.data(d))}})},strokes:function(j){if(j){return this.each(function(){var l=f(this),m=l.data(d);m.strokes=j})}else{var k=f(this).data(d);return k.strokes}},handler:function(j){return this.each(function(){var k=f(this),l=k.data(d);j(k,l)})},clear:function(){return this.each(function(){var j=f(this),k=j.data(d);k.canvas.clear();k.strokes=[];if(typeof i.events.clear==="function"){i.events.clear(j,k)}})},reset:function(j){return this.each(function(){var k=f(this),l=k.data(d);k.sketchable("destroy").sketchable(j);if(typeof i.events.reset==="function"){i.events.reset(k,l)}})},destroy:function(){return this.each(function(){var j=f(this),k=j.data(d);if(i.interactive){j.unbind("mousedown",g);j.unbind("mouseup",h);j.unbind("mousemove",e);j.unbind("touchstart",c);j.unbind("touchend",c);j.unbind("touchmove",c)}j.removeData(d);if(typeof i.events.destroy==="function"){i.events.destroy(j,k)}})}};f.fn.sketchable=function(j){if(a[j]){return a[j].apply(this,Array.prototype.slice.call(arguments,1))}else{if(typeof j==="object"||!j){return a.init.apply(this,arguments)}else{f.error("Method "+j+" does not exist on jQuery.sketchable")}}return this};f.fn.sketchable.defaults={interactive:true,events:{},graphics:{fillStyle:"#F0F",strokeStyle:"#F0F",lineWidth:2}};function b(k){var j=f(k.target),l=j.offset();return{x:k.pageX-l.left,y:k.pageY-l.top}}function e(m){var j=f(m.target),k=j.data(d);if(!k.canvas.isDrawing){return}var l=b(m);k.canvas.lineTo(l.x,l.y);k.coords.push([l.x,l.y,0]);if(typeof i.events.mouseMove==="function"){i.events.mouseMove(m)}}function g(m){var j=f(m.target),k=j.data(d);k.canvas.isDrawing=true;var l=b(m);k.canvas.beginPath();k.canvas.fillCircle(l.x,l.y,i.graphics.lineWidth);k.coords.push([l.x,l.y,1]);if(typeof i.events.mouseDown==="function"){i.events.mouseDown(m)}}function h(l){var j=f(l.target),k=j.data(d);k.canvas.isDrawing=false;k.canvas.closePath();k.strokes.push(k.coords);k.coords=[];if(typeof i.events.mouseUp==="function"){i.events.mouseUp(l)}}function c(k){k.preventDefault();var j=f(k.target);var l=k.originalEvent.changedTouches[0];l.type=k.type;switch(k.type){case"touchstart":j.unbind(k.type,g);g(l);break;case"touchmove":j.unbind(k.type,e);e(l);break;case"touchend":j.unbind(k.type,h);h(l);break;default:return}}})(jQuery); \ No newline at end of file diff --git a/jsketch.js b/jsketch.js new file mode 100644 index 0000000..6fcadb1 --- /dev/null +++ b/jsketch.js @@ -0,0 +1,383 @@ +/*! + * jSketch 0.6 | Luis A. Leiva | MIT license + * A lightweight JavaScript library for drawing facilities on HTML5 canvas. + */ +/** + * A simple JavaScript library for drawing facilities on HTML5 canvas. + * This class is mostly a wrapper for the HTML5 canvas API with some sugar, + * such as object chainability and old-school AS3-like notation. + * @name jSketch + * @class + * @author Luis Leiva + * @version 0.6 + * @date 16 Jan 2012 + * @since 2010 + * @example + * var canvas1 = document.getElementById('foo'); + * var canvas2 = document.getElementById('bar'); + * // instantiate once, reuse everywhere + * var brush = new jSketch(canvas1).lineStyle('red').moveTo(50,50).lineTo(10,10); + * brush.context(canvas2).beginFill('#5F7').fillCircle(30,30,8).endFill(); + */ +(function(window){ + /** + * @constructor + * @param {Object} elem MUST be a DOM element + * @param {Object} options configuration + */ + var jSketch = function(elem,options){ + return new Sketch(elem,options); + }; + // base class (private) + var Sketch = function(elem,options){ + // although discouraged, we can instantiate the class without arguments + if (!elem) return; + // one can pass default setup values + options = options || {}; + // set drawing context first + this.context(elem); + // scene defaults + this.stageWidth = elem.getAttribute("width"); + this.stageHeight = elem.getAttribute("height"); + // drawing defaults + this.graphics.fillStyle = options.fillStyle || '#F00'; + this.graphics.strokeStyle = options.strokeStyle || '#F0F'; + this.graphics.lineWidth = options.lineWidth || 2; + this.graphics.lineCap = options.lineCap || 'round'; + this.graphics.lineJoin = options.lineJoin || 'round'; + this.graphics.mitterLimit = options.mitterLimit || 10; + // make room for storing some data such as brush type, colors, etc. + this.data = {}; + // make constructor chainable + return this; + }; + /** + * jSketch methods (publicly extensible). + * @class + * @memberOf jSketch + * @see jSketch + */ + jSketch.fn = Sketch.prototype = { + /** + * Allows to change the drawing context at runtime. + * @param {Object} elem DOM element + * @return jSketch + * @name context + * @methodOf jSketch + */ + context: function(elem) { + if (elem == null) throw("No canvas element specified."); + // save shortcuts: canvas (DOM elem) & graphics (2D canvas context) + this.canvas = elem; + this.graphics = elem.getContext("2d"); + // allow chainability + return this; + }, + /** + * Sets the dimensions of canvas. + * @param {Number} width + * @param {Number} height + * @return jSketch + * @name size + * @methodOf jSketch + */ + size: function(width,height) { + this.stageWidth = width; + this.stageHeight = height; + this.canvas.width = width; + this.canvas.height = height; + return this; + }, + /** + * Sets the background color of canvas. + * @param {Number|String} color an HTML color + * @return jSketch + * @name background + * @methodOf jSketch + */ + background: function(color) { + var oldFill = this.graphics.fillStyle; + this.beginFill(color); + this.graphics.fillRect(0,0,this.stageWidth,this.stageHeight); + this.beginFill(oldFill); // restore old fill + return this; + }, + /** + * Shortcut for setting the size + background color. + * @param {Number} width + * @param {Number} height + * @param {Number|String} color an HTML color + * @return jSketch + * @name stage + * @methodOf jSketch + */ + stage: function(width,height,bgcolor) { + this.size(width,height).background(bgcolor); + return this; + }, + /** + * Sets the fill color. + * @param {Number|String} color an HTML color + * @return jSketch + * @name beginFill + * @methodOf jSketch + */ + beginFill: function(color) { + this.data.fillStyle = this.graphics.fillStyle; + this.graphics.fillStyle = color; + return this; + }, + /** + * Recovers the fill color that was set before beginFill(). + * @return jSketch + * @name endFill + * @methodOf jSketch + */ + endFill: function() { + this.graphics.fillStyle = this.data.fillStyle; + return this; + }, + /** + * Sets the line style. + * @param {Number|String} color an HTML color + * @param {Number} thickness line thickness + * @param {String} thickness style of line cap + * @param {String} joinStyle style of line join + * @param {String} mitter style of mitter + * @return jSketch + * @name lineStyle + * @methodOf jSketch + */ + lineStyle: function(color,thickness,capStyle,joinStyle,mitter) { + this.graphics.strokeStyle = color || this.graphics.strokeStyle; + this.graphics.lineWidth = thickness || this.graphics.lineWidth; + this.graphics.lineCap = capStyle || this.graphics.lineCap; + this.graphics.lineJoin = joinStyle || this.graphics.lineJoin; + this.graphics.mitterLimit = mitter || this.graphics.mitterLimit; + return this; + }, + /** + * Move brush to a coordinate in canvas. + * @param {Number} x + * @param {Number} y + * @return jSketch + * @name moveTo + * @methodOf jSketch + */ + moveTo: function(x,y) { + this.graphics.moveTo(x,y); + return this; + }, + /** + * Draws line to given coordinate. + * @param {Number} x + * @param {Number} y + * @return jSketch + * @name lineTo + * @methodOf jSketch + */ + lineTo: function(x,y) { + this.graphics.lineTo(x,y); + this.graphics.stroke(); + return this; + }, + /** + * Draws line from coordinate 1 to coordinate 2. + * @param {Number} x1 + * @param {Number} y1 + * @param {Number} x2 + * @param {Number} y2 + * @return jSketch + * @name line + * @methodOf jSketch + */ + line: function(x1,y1,x2,y2) { + this.graphics.moveTo(x1,y1); + this.lineTo(x2,y2); + return this; + }, + /** + * Draws curve to given coordinate. + * @param {Number} x + * @param {Number} y + * @param {Number} cpx x coordinate of control point + * @param {Number} cpy y coordinate of control point + * @return jSketch + * @name curveTo + * @methodOf jSketch + */ + curveTo: function(x,y,cpx,cpy) { + this.graphics.quadraticCurveTo(cpx,cpy,x,y); + this.graphics.stroke(); + return this; + }, + /** + * Draws curve from coordinate 1 to coordinate 2. + * @param {Number} x1 + * @param {Number} y1 + * @param {Number} x2 + * @param {Number} y2 + * @param {Number} cpx x coordinate of control point + * @param {Number} cpy y coordinate of control point + * @return jSketch + * @name curve + * @methodOf jSketch + */ + curve: function(x1,y1,x2,y2,cpx,cpy) { + this.graphics.moveTo(x1,y1); + this.curveTo(x2,y2,cpx,cpy); + return this; + }, + /** + * Draws a stroke-only rectangle. + * @param {Number} x + * @param {Number} y + * @param {Number} width + * @param {Number} height + * @return jSketch + * @name strokeRect + * @methodOf jSketch + */ + strokeRect: function(x,y,width,height) { + this.graphics.beginPath(); + //this.moveTo(x,y).lineTo(x+width,y).lineTo(x+width,y+height).lineTo(y,y+height).lineTo(x,y); + this.graphics.strokeRect(x,y,width,height); + this.graphics.closePath(); + return this; + }, + /** + * Draws a filled rectangle. + * @param {Number} x + * @param {Number} y + * @param {Number} width + * @param {Number} height + * @return jSketch + * @name fillRect + * @methodOf jSketch + */ + fillRect: function(x,y,width,height) { + this.graphics.beginPath(); + this.graphics.fillRect(x,y,width,height); + this.graphics.closePath(); + return this; + }, + /** + * Draws a stroke-only circle. + * @param {Number} x + * @param {Number} y + * @param {Number} radius + * @return jSketch + * @name strokeCircle + * @methodOf jSketch + */ + strokeCircle: function(x,y,radius) { + this.graphics.beginPath(); + this.graphics.arc(x,y, radius, 0, Math.PI * 2, false); + this.graphics.stroke(); + this.graphics.closePath(); + return this; + }, + /** + * Draws a filled circle. + * @param {Number} x + * @param {Number} y + * @param {Number} radius + * @return jSketch + * @name fillCircle + * @methodOf jSketch + */ + fillCircle: function(x,y,radius) { + this.graphics.beginPath(); + this.graphics.arc(x,y, radius, 0, Math.PI * 2, false); + this.graphics.fill(); + this.graphics.closePath(); + return this; + }, + // experimental + radialCircle: function(x,y,radius,color,glowSize){ + var g = this.graphics.createRadialGradient(x,y,radius,x,y,glowSize); + g.addColorStop(0,color); + g.addColorStop(1.0,"rgba(0,0,0,0)"); + this.graphics.fillStyle = g; + this.fillCircle(x,y,radius); + return this; + }, + /** + * A path is started. + * @return jSketch + * @name beginPath + * @methodOf jSketch + */ + beginPath: function() { + this.graphics.beginPath(); + return this; + }, + /** + * A path is finished. + * @return jSketch + * @name closePath + * @methodOf jSketch + */ + closePath: function() { + this.graphics.closePath(); + return this; + }, + /** + * Sets brush to eraser mode. + * @return jSketch + * @name eraser + * @methodOf jSketch + */ + eraser: function() { + this.data.strokeStyle = this.graphics.strokeStyle; + this.graphics.globalCompositeOperation = "copy"; + this.graphics.strokeStyle = "rgba(0,0,0,0)"; + }, + /** + * Sets brush to pencil mode. + * @return jSketch + * @name pencil + * @methodOf jSketch + */ + pencil: function() { + this.graphics.globalCompositeOperation = "source-over"; + this.graphics.strokeStyle = this.data.strokeStyle; + }, + /** + * Clears stage. + * @return jSketch + * @name clear + * @methodOf jSketch + */ + clear: function() { + this.graphics.clearRect(0,0, this.stageWidth,this.stageHeight); + //this.canvas.width = this.canvas.width; + this.data = {}; + return this; + }, + /** + * Saves a snapshot of all styles and transformations. + * @return jSketch + * @name save + * @methodOf jSketch + */ + save: function() { + this.graphics.save(); + return this; + }, + /** + * Restores previous drawing state. + * @return jSketch + * @name restore + * @methodOf jSketch + */ + restore: function() { + this.graphics.restore(); + return this; + } + }; + + // expose + window.jSketch = jSketch; + +})(this); diff --git a/jsketch.min.js b/jsketch.min.js new file mode 100644 index 0000000..a5efae8 --- /dev/null +++ b/jsketch.min.js @@ -0,0 +1,5 @@ +/* + * jSketch 0.6 | Luis A. Leiva | MIT license + * A simple JavaScript library for drawing facilities on HTML5 canvas. + */ +(function(a){var c=function(e,d){return new b(e,d)};var b=function(e,d){if(!e){return}d=d||{};this.context(e);this.stageWidth=e.getAttribute("width");this.stageHeight=e.getAttribute("height");this.graphics.fillStyle=d.fillStyle||"#F00";this.graphics.strokeStyle=d.strokeStyle||"#F0F";this.graphics.lineWidth=d.lineWidth||2;this.graphics.lineCap=d.lineCap||"round";this.graphics.lineJoin=d.lineJoin||"round";this.graphics.mitterLimit=d.mitterLimit||10;this.data={};return this};c.fn=b.prototype={context:function(d){if(d==null){throw ("No canvas element specified.")}this.canvas=d;this.graphics=d.getContext("2d");return this},size:function(e,d){this.stageWidth=e;this.stageHeight=d;this.canvas.width=e;this.canvas.height=d;return this},background:function(d){var e=this.graphics.fillStyle;this.beginFill(d);this.graphics.fillRect(0,0,this.stageWidth,this.stageHeight);this.beginFill(e);return this},stage:function(f,d,e){this.size(f,d).background(e);return this},beginFill:function(d){this.data.fillStyle=this.graphics.fillStyle;this.graphics.fillStyle=d;return this},endFill:function(){this.graphics.fillStyle=this.data.fillStyle;return this},lineStyle:function(d,e,f,h,g){this.graphics.strokeStyle=d||this.graphics.strokeStyle;this.graphics.lineWidth=e||this.graphics.lineWidth;this.graphics.lineCap=f||this.graphics.lineCap;this.graphics.lineJoin=h||this.graphics.lineJoin;this.graphics.mitterLimit=g||this.graphics.mitterLimit;return this},moveTo:function(d,e){this.graphics.moveTo(d,e);return this},lineTo:function(d,e){this.graphics.lineTo(d,e);this.graphics.stroke();return this},line:function(e,g,d,f){this.graphics.moveTo(e,g);this.lineTo(d,f);return this},curveTo:function(d,g,f,e){this.graphics.quadraticCurveTo(f,e,d,g);this.graphics.stroke();return this},curve:function(f,i,d,h,g,e){this.graphics.moveTo(f,i);this.curveTo(d,h,g,e);return this},strokeRect:function(e,g,f,d){this.graphics.beginPath();this.graphics.strokeRect(e,g,f,d);this.graphics.closePath();return this},fillRect:function(e,g,f,d){this.graphics.beginPath();this.graphics.fillRect(e,g,f,d);this.graphics.closePath();return this},strokeCircle:function(e,f,d){this.graphics.beginPath();this.graphics.arc(e,f,d,0,Math.PI*2,false);this.graphics.stroke();this.graphics.closePath();return this},fillCircle:function(e,f,d){this.graphics.beginPath();this.graphics.arc(e,f,d,0,Math.PI*2,false);this.graphics.fill();this.graphics.closePath();return this},radialCircle:function(e,j,d,f,h){var i=this.graphics.createRadialGradient(e,j,d,e,j,h);i.addColorStop(0,f);i.addColorStop(1,"rgba(0,0,0,0)");this.graphics.fillStyle=i;this.fillCircle(e,j,d);return this},beginPath:function(){this.graphics.beginPath();return this},closePath:function(){this.graphics.closePath();return this},eraser:function(){this.data.strokeStyle=this.graphics.strokeStyle;this.graphics.globalCompositeOperation="copy";this.graphics.strokeStyle="rgba(0,0,0,0)"},pencil:function(){this.graphics.globalCompositeOperation="source-over";this.graphics.strokeStyle=this.data.strokeStyle},clear:function(){this.graphics.clearRect(0,0,this.stageWidth,this.stageHeight);this.data={};return this},save:function(){this.graphics.save();return this},restore:function(){this.graphics.restore();return this}};a.jSketch=c})(this); \ No newline at end of file