├── LICENSE ├── README.md ├── demo.html ├── demo_images ├── arcs.png ├── beziercurve.png ├── circles.png ├── ellipses.png ├── lines.png ├── quadraticcurve.png ├── segSizeShaky.png └── squares.png ├── demo_require.html ├── require.js ├── requireLICENSE ├── shaky.js ├── shakydemo.js └── shakydemorequire.js /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Keith Peters 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | shaky 2 | ==== 3 | 4 | When talking about traditional drawing on paper, many people say, "I can't draw a straight line." But with traditional computer graphics, you can usually ONLY draw straight lines. Let's fix that. 5 | 6 | shaky is a Canvas/Context2D wrapper that adds shaky drawing methods. Most of the drawing related methods of Context2D are proxied, either directly, or into shaky version. In addition, there are a few new useful shaky shape drawing methods. 7 | 8 | ### Methods: 9 | 10 | setSize(width, height) // sets the size of the canvas 11 | clear() // clears the canvas 12 | beginPath() // straight proxy 13 | stroke() // straight proxy 14 | fill() // straight proxy 15 | rect(x, y, w, h) // draws a shaky rectangle 16 | fillRect(x, y, w, h) // fills a shaky rectangle 17 | clearRect(x, y, w, h) // straight proxy 18 | strokeRect(x, y, w, h) // strokes a shaky rectangle 19 | moveTo(x, y) // moves to a point near the x, y point specified 20 | lineTo(x, y, exactEnd) // draws a shaky line to a point near x, y, or exactly to x, y if exactEnd is true. 21 | arc(x, y, r, start, end) // draws a shaky arc 22 | circle(x, y, r) // draws a shaky circle 23 | fillCircle(x, y, r) // fills a shaky circle 24 | strokeCircle(x, y, r) // strokes a shaky circle 25 | ellipse(x, y, xr, yr) // draws a shaky ellipse with a center of x, y, an x radius of xr and y radius of yr 26 | fillEllipse(x, y, xr, yr) // fills a shaky ellipse 27 | strokeEllipse(x, y, xr, yr) // strokes a shaky ellipse 28 | bezierCurveTo(x1, y1, x2, y2, x3, y3) // draws a shaky bezier curve 29 | quadraticCurveTo(x1, y1, x2, y2) // draws a shaky quadratic curve 30 | 31 | Create a shaky instance using: 32 | 33 | shaky.create(canvas); 34 | 35 | The canvas parameter can be a reference to a canvas object, or the string id of a canvas element on the page. 36 | 37 | ### Properties: 38 | 39 | width and height: read the current size of the canvas. use the setSize method to change these. 40 | canvas: a reference to the canvas that this shaky instance is wrapping. 41 | context: a reference to the context2d that this shaky instance is wrapping. 42 | segSize: controls the resolution of this shaky instance, described below. 43 | shake: the shakiness of this shaky instance, described below. 44 | 45 | ### segSize and shake: 46 | 47 | segSize controls the resolution of the shaky instance. Say you use lineTo(x, y). Instead of drawing a single line from the current location to the new location, shaky will draw a series of short line segments between the two points. segSize specifies approximately how long those line segments will be. For example, if segSize = 10 and you draw a line from 0, 0, to 0, 100, it will draw 10 line segments, each approximately 10 pixels long. In reality, most will be longer, due to shake. 48 | 49 | shake controls the random offset of each point or line segment. shake is a total range so if shake is 10 and you do a moveTo to 100, 100, you will actually wind up moving to somewhere from 95, 95 to 105, 105 50 | 51 | Experiment changing both segSize and shake to create a lot of different shaky effects. 52 | 53 | ### Demo images 54 | 55 | ![squares](demo_images/squares.png "Squares") 56 | ![lines](demo_images/lines.png "Lines") 57 | ![arcs](demo_images/arcs.png "Arcs") 58 | ![circles](demo_images/circles.png "Circles") 59 | ![ellipses](demo_images/ellipses.png "Ellipses") 60 | ![quadratic curve](demo_images/quadraticcurve.png "Quadratic Curve") 61 | ![bezier curve](demo_images/beziercurve.png "Bezier Curve") 62 | 63 | This shows the relationship of the segSize and shaky properties. Here, shaky increases left to right, and segSize decreases top to bottom. 64 | 65 | ![segSize and shaky](demo_images/segSizeShaky.png "segSize and shaky properties") 66 | 67 | -------------------------------------------------------------------------------- /demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ColorLib 5 | 6 | 14 | 15 | 16 | 17 | 18 |
19 | 20 |
21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /demo_images/arcs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit101/shaky/1142b6214af088ad4c2b7a9db2b62b935c8660fa/demo_images/arcs.png -------------------------------------------------------------------------------- /demo_images/beziercurve.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit101/shaky/1142b6214af088ad4c2b7a9db2b62b935c8660fa/demo_images/beziercurve.png -------------------------------------------------------------------------------- /demo_images/circles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit101/shaky/1142b6214af088ad4c2b7a9db2b62b935c8660fa/demo_images/circles.png -------------------------------------------------------------------------------- /demo_images/ellipses.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit101/shaky/1142b6214af088ad4c2b7a9db2b62b935c8660fa/demo_images/ellipses.png -------------------------------------------------------------------------------- /demo_images/lines.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit101/shaky/1142b6214af088ad4c2b7a9db2b62b935c8660fa/demo_images/lines.png -------------------------------------------------------------------------------- /demo_images/quadraticcurve.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit101/shaky/1142b6214af088ad4c2b7a9db2b62b935c8660fa/demo_images/quadraticcurve.png -------------------------------------------------------------------------------- /demo_images/segSizeShaky.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit101/shaky/1142b6214af088ad4c2b7a9db2b62b935c8660fa/demo_images/segSizeShaky.png -------------------------------------------------------------------------------- /demo_images/squares.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bit101/shaky/1142b6214af088ad4c2b7a9db2b62b935c8660fa/demo_images/squares.png -------------------------------------------------------------------------------- /demo_require.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ColorLib 5 | 6 | 14 | 15 | 16 | 17 | 18 |
19 | 20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /require.js: -------------------------------------------------------------------------------- 1 | /* 2 | RequireJS 1.0.8 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved. 3 | Available via the MIT or new BSD license. 4 | see: http://github.com/jrburke/requirejs for details 5 | */ 6 | var requirejs,require,define; 7 | (function(r){function K(a){return O.call(a)==="[object Function]"}function G(a){return O.call(a)==="[object Array]"}function $(a,c,l){for(var j in c)if(!(j in L)&&(!(j in a)||l))a[j]=c[j];return d}function P(a,c,d){a=Error(c+"\nhttp://requirejs.org/docs/errors.html#"+a);if(d)a.originalError=d;return a}function aa(a,c,d){var j,k,t;for(j=0;t=c[j];j++){t=typeof t==="string"?{name:t}:t;k=t.location;if(d&&(!k||k.indexOf("/")!==0&&k.indexOf(":")===-1))k=d+"/"+(k||t.name);a[t.name]={name:t.name,location:k|| 8 | t.name,main:(t.main||"main").replace(fa,"").replace(ba,"")}}}function V(a,c){a.holdReady?a.holdReady(c):c?a.readyWait+=1:a.ready(!0)}function ga(a){function c(b,f){var g,m;if(b&&b.charAt(0)===".")if(f){q.pkgs[f]?f=[f]:(f=f.split("/"),f=f.slice(0,f.length-1));g=b=f.concat(b.split("/"));var a;for(m=0;a=g[m];m++)if(a===".")g.splice(m,1),m-=1;else if(a==="..")if(m===1&&(g[2]===".."||g[0]===".."))break;else m>0&&(g.splice(m-1,2),m-=2);m=q.pkgs[g=b[0]];b=b.join("/");m&&b===g+"/"+m.main&&(b=g)}else b.indexOf("./")=== 9 | 0&&(b=b.substring(2));return b}function l(b,f){var g=b?b.indexOf("!"):-1,m=null,a=f?f.name:null,h=b,e,d;g!==-1&&(m=b.substring(0,g),b=b.substring(g+1,b.length));m&&(m=c(m,a));b&&(m?e=(g=n[m])&&g.normalize?g.normalize(b,function(b){return c(b,a)}):c(b,a):(e=c(b,a),d=G[e],d||(d=i.nameToUrl(b,null,f),G[e]=d)));return{prefix:m,name:e,parentMap:f,url:d,originalName:h,fullName:m?m+"!"+(e||""):e}}function j(){var b=!0,f=q.priorityWait,g,a;if(f){for(a=0;g=f[a];a++)if(!s[g]){b=!1;break}b&&delete q.priorityWait}return b} 10 | function k(b,f,g){return function(){var a=ha.call(arguments,0),c;if(g&&K(c=a[a.length-1]))c.__requireJsBuild=!0;a.push(f);return b.apply(null,a)}}function t(b,f,g){f=k(g||i.require,b,f);$(f,{nameToUrl:k(i.nameToUrl,b),toUrl:k(i.toUrl,b),defined:k(i.requireDefined,b),specified:k(i.requireSpecified,b),isBrowser:d.isBrowser});return f}function p(b){var f,g,a,c=b.callback,h=b.map,e=h.fullName,ca=b.deps;a=b.listeners;var j=q.requireExecCb||d.execCb;if(c&&K(c)){if(q.catchError.define)try{g=j(e,b.callback, 11 | ca,n[e])}catch(k){f=k}else g=j(e,b.callback,ca,n[e]);if(e)(c=b.cjsModule)&&c.exports!==r&&c.exports!==n[e]?g=n[e]=b.cjsModule.exports:g===r&&b.usingExports?g=n[e]:(n[e]=g,H[e]&&(T[e]=!0))}else e&&(g=n[e]=c,H[e]&&(T[e]=!0));if(x[b.id])delete x[b.id],b.isDone=!0,i.waitCount-=1,i.waitCount===0&&(J=[]);delete M[e];if(d.onResourceLoad&&!b.placeholder)d.onResourceLoad(i,h,b.depArray);if(f)return g=(e?l(e).url:"")||f.fileName||f.sourceURL,a=f.moduleTree,f=P("defineerror",'Error evaluating module "'+e+'" at location "'+ 12 | g+'":\n'+f+"\nfileName:"+g+"\nlineNumber: "+(f.lineNumber||f.line),f),f.moduleName=e,f.moduleTree=a,d.onError(f);for(f=0;c=a[f];f++)c(g);return r}function u(b,f){return function(g){b.depDone[f]||(b.depDone[f]=!0,b.deps[f]=g,b.depCount-=1,b.depCount||p(b))}}function o(b,f){var g=f.map,a=g.fullName,c=g.name,h=N[b]||(N[b]=n[b]),e;if(!f.loading)f.loading=!0,e=function(b){f.callback=function(){return b};p(f);s[f.id]=!0;A()},e.fromText=function(b,f){var g=Q;s[b]=!1;i.scriptCount+=1;i.fake[b]=!0;g&&(Q=!1); 13 | d.exec(f);g&&(Q=!0);i.completeLoad(b)},a in n?e(n[a]):h.load(c,t(g.parentMap,!0,function(b,a){var c=[],e,m;for(e=0;m=b[e];e++)m=l(m,g.parentMap),b[e]=m.fullName,m.prefix||c.push(b[e]);f.moduleDeps=(f.moduleDeps||[]).concat(c);return i.require(b,a)}),e,q)}function y(b){x[b.id]||(x[b.id]=b,J.push(b),i.waitCount+=1)}function D(b){this.listeners.push(b)}function v(b,f){var g=b.fullName,a=b.prefix,c=a?N[a]||(N[a]=n[a]):null,h,e;g&&(h=M[g]);if(!h&&(e=!0,h={id:(a&&!c?O++ +"__p@:":"")+(g||"__r@"+O++),map:b, 14 | depCount:0,depDone:[],depCallbacks:[],deps:[],listeners:[],add:D},B[h.id]=!0,g&&(!a||N[a])))M[g]=h;a&&!c?(g=l(a),a in n&&!n[a]&&(delete n[a],delete R[g.url]),a=v(g,!0),a.add(function(){var f=l(b.originalName,b.parentMap),f=v(f,!0);h.placeholder=!0;f.add(function(b){h.callback=function(){return b};p(h)})})):e&&f&&(s[h.id]=!1,i.paused.push(h),y(h));return h}function C(b,f,a,c){var b=l(b,c),d=b.name,h=b.fullName,e=v(b),j=e.id,k=e.deps,o;if(h){if(h in n||s[j]===!0||h==="jquery"&&q.jQuery&&q.jQuery!== 15 | a().fn.jquery)return;B[j]=!0;s[j]=!0;h==="jquery"&&a&&W(a())}e.depArray=f;e.callback=a;for(a=0;a0)return r;if(q.priorityWait)if(j())A();else return r;for(h in s)if(!(h in L)&&(c=!0,!s[h]))if(b)a+=h+" ";else if(l=!0,h.indexOf("!")===-1){k=[];break}else(e=M[h]&&M[h].moduleDeps)&&k.push.apply(k,e);if(!c&&!i.waitCount)return r;if(b&&a)return b=P("timeout","Load timeout for modules: "+a),b.requireType="timeout",b.requireModules=a,b.contextName=i.contextName,d.onError(b); 18 | if(l&&k.length)for(a=0;h=x[k[a]];a++)if(h=F(h,{})){z(h,{});break}if(!b&&(l||i.scriptCount)){if((I||da)&&!X)X=setTimeout(function(){X=0;E()},50);return r}if(i.waitCount){for(a=0;h=J[a];a++)z(h,{});i.paused.length&&A();Y<5&&(Y+=1,E())}Y=0;d.checkReadyState();return r}var i,A,q={waitSeconds:7,baseUrl:"./",paths:{},pkgs:{},catchError:{}},S=[],B={require:!0,exports:!0,module:!0},G={},n={},s={},x={},J=[],R={},O=0,M={},N={},H={},T={},Z=0;W=function(b){if(!i.jQuery&&(b=b||(typeof jQuery!=="undefined"?jQuery: 19 | null))&&!(q.jQuery&&b.fn.jquery!==q.jQuery)&&("holdReady"in b||"readyWait"in b))if(i.jQuery=b,w(["jquery",[],function(){return jQuery}]),i.scriptCount)V(b,!0),i.jQueryIncremented=!0};A=function(){var b,a,c,l,k,h;i.takeGlobalQueue();Z+=1;if(i.scriptCount<=0)i.scriptCount=0;for(;S.length;)if(b=S.shift(),b[0]===null)return d.onError(P("mismatch","Mismatched anonymous define() module: "+b[b.length-1]));else w(b);if(!q.priorityWait||j())for(;i.paused.length;){k=i.paused;i.pausedCount+=k.length;i.paused= 20 | [];for(l=0;b=k[l];l++)a=b.map,c=a.url,h=a.fullName,a.prefix?o(a.prefix,b):!R[c]&&!s[h]&&((q.requireLoad||d.load)(i,h,c),c.indexOf("empty:")!==0&&(R[c]=!0));i.startTime=(new Date).getTime();i.pausedCount-=k.length}Z===1&&E();Z-=1;return r};i={contextName:a,config:q,defQueue:S,waiting:x,waitCount:0,specified:B,loaded:s,urlMap:G,urlFetched:R,scriptCount:0,defined:n,paused:[],pausedCount:0,plugins:N,needFullExec:H,fake:{},fullExec:T,managerCallbacks:M,makeModuleMap:l,normalize:c,configure:function(b){var a, 21 | c,d;b.baseUrl&&b.baseUrl.charAt(b.baseUrl.length-1)!=="/"&&(b.baseUrl+="/");a=q.paths;d=q.pkgs;$(q,b,!0);if(b.paths){for(c in b.paths)c in L||(a[c]=b.paths[c]);q.paths=a}if((a=b.packagePaths)||b.packages){if(a)for(c in a)c in L||aa(d,a[c],c);b.packages&&aa(d,b.packages);q.pkgs=d}if(b.priority)c=i.requireWait,i.requireWait=!1,A(),i.require(b.priority),A(),i.requireWait=c,q.priorityWait=b.priority;if(b.deps||b.callback)i.require(b.deps||[],b.callback)},requireDefined:function(b,a){return l(b,a).fullName in 22 | n},requireSpecified:function(b,a){return l(b,a).fullName in B},require:function(b,c,g){if(typeof b==="string"){if(K(c))return d.onError(P("requireargs","Invalid require call"));if(d.get)return d.get(i,b,c);c=l(b,c);b=c.fullName;return!(b in n)?d.onError(P("notloaded","Module name '"+c.fullName+"' has not been loaded yet for context: "+a)):n[b]}(b&&b.length||c)&&C(null,b,c,g);if(!i.requireWait)for(;!i.scriptCount&&i.paused.length;)A();return i.require},takeGlobalQueue:function(){U.length&&(ja.apply(i.defQueue, 23 | [i.defQueue.length-1,0].concat(U)),U=[])},completeLoad:function(b){var a;for(i.takeGlobalQueue();S.length;)if(a=S.shift(),a[0]===null){a[0]=b;break}else if(a[0]===b)break;else w(a),a=null;a?w(a):w([b,[],b==="jquery"&&typeof jQuery!=="undefined"?function(){return jQuery}:null]);d.isAsync&&(i.scriptCount-=1);A();d.isAsync||(i.scriptCount-=1)},toUrl:function(b,a){var c=b.lastIndexOf("."),d=null;c!==-1&&(d=b.substring(c,b.length),b=b.substring(0,c));return i.nameToUrl(b,d,a)},nameToUrl:function(b,a,g){var l, 24 | k,h,e,j=i.config,b=c(b,g&&g.fullName);if(d.jsExtRegExp.test(b))a=b+(a?a:"");else{l=j.paths;k=j.pkgs;g=b.split("/");for(e=g.length;e>0;e--)if(h=g.slice(0,e).join("/"),l[h]){g.splice(0,e,l[h]);break}else if(h=k[h]){b=b===h.name?h.location+"/"+h.main:h.location;g.splice(0,e,b);break}a=g.join("/")+(a||".js");a=(a.charAt(0)==="/"||a.match(/^[\w\+\.\-]+:/)?"":j.baseUrl)+a}return j.urlArgs?a+((a.indexOf("?")===-1?"?":"&")+j.urlArgs):a}};i.jQueryCheck=W;i.resume=A;return i}function ka(){var a,c,d;if(C&&C.readyState=== 25 | "interactive")return C;a=document.getElementsByTagName("script");for(c=a.length-1;c>-1&&(d=a[c]);c--)if(d.readyState==="interactive")return C=d;return null}var la=/(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,ma=/require\(\s*["']([^'"\s]+)["']\s*\)/g,fa=/^\.\//,ba=/\.js$/,O=Object.prototype.toString,u=Array.prototype,ha=u.slice,ja=u.splice,I=!!(typeof window!=="undefined"&&navigator&&document),da=!I&&typeof importScripts!=="undefined",na=I&&navigator.platform==="PLAYSTATION 3"?/^complete$/:/^(complete|loaded)$/, 26 | ea=typeof opera!=="undefined"&&opera.toString()==="[object Opera]",L={},D={},U=[],C=null,Y=0,Q=!1,ia={require:!0,module:!0,exports:!0},d,u={},J,y,v,E,o,w,F,B,z,W,X;if(typeof define==="undefined"){if(typeof requirejs!=="undefined")if(K(requirejs))return;else u=requirejs,requirejs=r;typeof require!=="undefined"&&!K(require)&&(u=require,require=r);d=requirejs=function(a,c,d){var j="_",k;!G(a)&&typeof a!=="string"&&(k=a,G(c)?(a=c,c=d):a=[]);if(k&&k.context)j=k.context;d=D[j]||(D[j]=ga(j));k&&d.configure(k); 27 | return d.require(a,c)};d.config=function(a){return d(a)};require||(require=d);d.toUrl=function(a){return D._.toUrl(a)};d.version="1.0.8";d.jsExtRegExp=/^\/|:|\?|\.js$/;y=d.s={contexts:D,skipAsync:{}};if(d.isAsync=d.isBrowser=I)if(v=y.head=document.getElementsByTagName("head")[0],E=document.getElementsByTagName("base")[0])v=y.head=E.parentNode;d.onError=function(a){throw a;};d.load=function(a,c,l){d.resourcesReady(!1);a.scriptCount+=1;d.attach(l,a,c);if(a.jQuery&&!a.jQueryIncremented)V(a.jQuery,!0), 28 | a.jQueryIncremented=!0};define=function(a,c,d){var j,k;typeof a!=="string"&&(d=c,c=a,a=null);G(c)||(d=c,c=[]);!c.length&&K(d)&&d.length&&(d.toString().replace(la,"").replace(ma,function(a,d){c.push(d)}),c=(d.length===1?["require"]:["require","exports","module"]).concat(c));if(Q&&(j=J||ka()))a||(a=j.getAttribute("data-requiremodule")),k=D[j.getAttribute("data-requirecontext")];(k?k.defQueue:U).push([a,c,d]);return r};define.amd={multiversion:!0,plugins:!0,jQuery:!0};d.exec=function(a){return eval(a)}; 29 | d.execCb=function(a,c,d,j){return c.apply(j,d)};d.addScriptToDom=function(a){J=a;E?v.insertBefore(a,E):v.appendChild(a);J=null};d.onScriptLoad=function(a){var c=a.currentTarget||a.srcElement,l;if(a.type==="load"||c&&na.test(c.readyState))C=null,a=c.getAttribute("data-requirecontext"),l=c.getAttribute("data-requiremodule"),D[a].completeLoad(l),c.detachEvent&&!ea?c.detachEvent("onreadystatechange",d.onScriptLoad):c.removeEventListener("load",d.onScriptLoad,!1)};d.attach=function(a,c,l,j,k,o){var p; 30 | if(I)return j=j||d.onScriptLoad,p=c&&c.config&&c.config.xhtml?document.createElementNS("http://www.w3.org/1999/xhtml","html:script"):document.createElement("script"),p.type=k||c&&c.config.scriptType||"text/javascript",p.charset="utf-8",p.async=!y.skipAsync[a],c&&p.setAttribute("data-requirecontext",c.contextName),p.setAttribute("data-requiremodule",l),p.attachEvent&&!(p.attachEvent.toString&&p.attachEvent.toString().indexOf("[native code]")<0)&&!ea?(Q=!0,o?p.onreadystatechange=function(){if(p.readyState=== 31 | "loaded")p.onreadystatechange=null,p.attachEvent("onreadystatechange",j),o(p)}:p.attachEvent("onreadystatechange",j)):p.addEventListener("load",j,!1),p.src=a,o||d.addScriptToDom(p),p;else da&&(importScripts(a),c.completeLoad(l));return null};if(I){o=document.getElementsByTagName("script");for(B=o.length-1;B>-1&&(w=o[B]);B--){if(!v)v=w.parentNode;if(F=w.getAttribute("data-main")){if(!u.baseUrl)o=F.split("/"),w=o.pop(),o=o.length?o.join("/")+"/":"./",u.baseUrl=o,F=w.replace(ba,"");u.deps=u.deps?u.deps.concat(F): 32 | [F];break}}}d.checkReadyState=function(){var a=y.contexts,c;for(c in a)if(!(c in L)&&a[c].waitCount)return;d.resourcesReady(!0)};d.resourcesReady=function(a){var c,l;d.resourcesDone=a;if(d.resourcesDone)for(l in a=y.contexts,a)if(!(l in L)&&(c=a[l],c.jQueryIncremented))V(c.jQuery,!1),c.jQueryIncremented=!1};d.pageLoaded=function(){if(document.readyState!=="complete")document.readyState="complete"};if(I&&document.addEventListener&&!document.readyState)document.readyState="loading",window.addEventListener("load", 33 | d.pageLoaded,!1);d(u);if(d.isAsync&&typeof setTimeout!=="undefined")z=y.contexts[u.context||"_"],z.requireWait=!0,setTimeout(function(){z.requireWait=!1;z.scriptCount||z.resume();d.checkReadyState()},0)}})(); 34 | -------------------------------------------------------------------------------- /requireLICENSE: -------------------------------------------------------------------------------- 1 | RequireJS is released under two licenses: new BSD, and MIT. You may pick the 2 | license that best suits your development needs. The text of both licenses are 3 | provided below. 4 | 5 | 6 | The "New" BSD License: 7 | ---------------------- 8 | 9 | Copyright (c) 2010-2014, The Dojo Foundation 10 | All rights reserved. 11 | 12 | Redistribution and use in source and binary forms, with or without 13 | modification, are permitted provided that the following conditions are met: 14 | 15 | * Redistributions of source code must retain the above copyright notice, this 16 | list of conditions and the following disclaimer. 17 | * Redistributions in binary form must reproduce the above copyright notice, 18 | this list of conditions and the following disclaimer in the documentation 19 | and/or other materials provided with the distribution. 20 | * Neither the name of the Dojo Foundation nor the names of its contributors 21 | may be used to endorse or promote products derived from this software 22 | without specific prior written permission. 23 | 24 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 25 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 28 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 30 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 31 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 32 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | 35 | 36 | 37 | MIT License 38 | ----------- 39 | 40 | Copyright (c) 2010-2014, The Dojo Foundation 41 | 42 | Permission is hereby granted, free of charge, to any person obtaining a copy 43 | of this software and associated documentation files (the "Software"), to deal 44 | in the Software without restriction, including without limitation the rights 45 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 46 | copies of the Software, and to permit persons to whom the Software is 47 | furnished to do so, subject to the following conditions: 48 | 49 | The above copyright notice and this permission notice shall be included in 50 | all copies or substantial portions of the Software. 51 | 52 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 53 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 54 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 55 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 56 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 57 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 58 | THE SOFTWARE. 59 | -------------------------------------------------------------------------------- /shaky.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var shaky = { 3 | canvas: null, 4 | context: null, 5 | segSize: 6, 6 | shake: 3, 7 | x: 0, 8 | y: 0, 9 | prevX: 0, 10 | prevY: 0, 11 | width: 0, 12 | height: 0, 13 | 14 | create: function(canvas) { 15 | var obj = Object.create(this); 16 | if(typeof canvas === "string") { 17 | canvas = document.getElementById(canvas); 18 | } 19 | obj.canvas = canvas; 20 | obj.context = obj.canvas.getContext("2d"); 21 | obj.width = obj.canvas.width; 22 | obj.height = obj.canvas.height; 23 | return obj; 24 | }, 25 | 26 | setSize: function(width, height) { 27 | this.canvas.width = this.width = width; 28 | this.canvas.height = this.height = height; 29 | }, 30 | 31 | clear: function() { 32 | this.context.clearRect(0, 0, this.width, this.height); 33 | }, 34 | 35 | beginPath: function() { 36 | this.context.beginPath(); 37 | }, 38 | 39 | stroke: function() { 40 | this.context.stroke(); 41 | }, 42 | 43 | fill: function() { 44 | this.context.fill(); 45 | }, 46 | 47 | rect: function(x, y, w, h) { 48 | this.moveTo(x, y); 49 | var startX = this.x, 50 | startY = this.y; 51 | this.lineTo(x + w, y); 52 | this.lineTo(x + w, y + h); 53 | this.lineTo(x, y + h); 54 | this.lineTo(startX, startY, true); 55 | }, 56 | 57 | fillRect: function(x, y, w, h) { 58 | this.beginPath(); 59 | this.rect(x, y, w, h); 60 | this.fill(); 61 | }, 62 | 63 | clearRect: function(x, y, w, h) { 64 | this.context.clearRect(x, y, w, h); 65 | }, 66 | 67 | strokeRect: function(x, y, w, h) { 68 | this.beginPath(); 69 | this.rect(x, y, w, h); 70 | this.stroke(); 71 | }, 72 | 73 | moveTo: function(x, y) { 74 | this._setXY(x + Math.random() * this.shake - this.shake / 2, 75 | y + Math.random() * this.shake - this.shake / 2) 76 | this.context.moveTo(this.x, this.y); 77 | }, 78 | 79 | lineTo: function(x, y, exactEnd) { 80 | var toX = exactEnd ? x : x + Math.random() * this.shake - this.shake / 2, 81 | toY = exactEnd ? y : y + Math.random() * this.shake - this.shake / 2 82 | dx = toX - this.x, 83 | dy = toY - this.y, 84 | dist = Math.sqrt(dx * dx + dy * dy), 85 | steps = Math.floor(dist / this.segSize), 86 | resX = dx / steps, 87 | resY = dy / steps; 88 | 89 | for(var i = 1; i < steps; i++) { 90 | this.context.lineTo(this.x + resX * i + Math.random() * this.shake - this.shake / 2, 91 | this.y + resY * i + Math.random() * this.shake - this.shake / 2); 92 | } 93 | this.context.lineTo(toX, toY); 94 | this._setXY(toX, toY); 95 | }, 96 | 97 | arc: function(x, y, r, start, end) { 98 | while(end < start) end += Math.PI * 2; 99 | 100 | this.moveTo(x + Math.cos(start) * r, 101 | y + Math.sin(start) * r); 102 | var slice = Math.PI * 2 / Math.floor(r * Math.PI * 2 / this.segSize); 103 | 104 | for(var angle = start + slice; angle < end; angle += slice) { 105 | this.context.lineTo(x + Math.cos(angle) * r + Math.random() * this.shake - this.shake / 2, 106 | y + Math.sin(angle) * r + Math.random() * this.shake - this.shake / 2); 107 | } 108 | this._setXY(x + Math.cos(end) * r + Math.random() * this.shake - this.shake / 2, 109 | y + Math.sin(end) * r + Math.random() * this.shake - this.shake / 2); 110 | this.context.lineTo(this.x, this.y); 111 | }, 112 | 113 | circle: function(x, y, r) { 114 | var slice = Math.PI * 2 / Math.floor(r * Math.PI * 2 / this.segSize); 115 | this.arc(x, y, r, 0, Math.PI * 2 - slice); 116 | this._setXY(this.prevX, this.prevY); 117 | this.context.lineTo(this.x, this.y); 118 | }, 119 | 120 | fillCircle: function(x, y, r) { 121 | this.beginPath(); 122 | this.circle(x, y, r); 123 | this.fill(); 124 | }, 125 | 126 | strokeCircle: function(x, y, r) { 127 | this.beginPath(); 128 | this.circle(x, y, r); 129 | this.stroke(); 130 | }, 131 | 132 | ellipse: function(x, y, xr, yr) { 133 | this.moveTo(x + xr, y); 134 | var slice = Math.PI * 2 / Math.floor((xr + yr) / 2 * Math.PI * 2 / this.segSize); 135 | 136 | for(var angle = slice; angle < Math.PI * 2 - slice; angle += slice) { 137 | this.context.lineTo(x + Math.cos(angle) * xr + Math.random() * this.shake - this.shake / 2, 138 | y + Math.sin(angle) * yr + Math.random() * this.shake - this.shake / 2); 139 | } 140 | this.context.lineTo(this.x, this.y); 141 | 142 | }, 143 | 144 | fillEllipse: function(x, y, xr, yr) { 145 | this.beginPath(); 146 | this.ellipse(x, y, xr, yr); 147 | this.fill(); 148 | }, 149 | 150 | strokeEllipse: function(x, y, xr, yr) { 151 | this.beginPath(); 152 | this.ellipse(x, y, xr, yr); 153 | this.stroke(); 154 | }, 155 | 156 | bezierCurveTo: function(x1, y1, x2, y2, x3, y3) { 157 | var x0 = this.x, 158 | y0 = this.y, 159 | distance = this._distance(x0, y0, x1, y1) + this._distance(x1, y1, x2, y2) + this._distance(x2, y2, x3, y3), 160 | res = this.segSize / distance; 161 | 162 | for(var t = 0; t < 1; t += res) { 163 | this.context.lineTo(Math.pow(1 - t, 3) * x0 + 164 | 3 * Math.pow(1 - t, 2) * t * x1 + 165 | 3 * (1 - t) * t * t * x2 + 166 | t * t * t * x3 + 167 | Math.random() * this.shake - this.shake / 2, 168 | Math.pow(1 - t, 3) * y0 + 169 | 3 * Math.pow(1 - t, 2) * t * y1 + 170 | 3 * (1 - t) * t * t * y2 + 171 | t * t * t * y3 + 172 | Math.random() * this.shake - this.shake / 2); 173 | } 174 | this._setXY(x3 + Math.random() * this.shake - this.shake / 2, 175 | y3 + Math.random() * this.shake - this.shake / 2); 176 | this.context.lineTo(this.x, this.y); 177 | }, 178 | 179 | quadraticCurveTo: function(x1, y1, x2, y2) { 180 | var x0 = this.x, 181 | y0 = this.y, 182 | distance = this._distance(x0, y0, x1, y1) + this._distance(x1, y1, x2, y2), 183 | res = this.segSize / distance; 184 | 185 | for(var t = 0; t < 1; t += res) { 186 | this.context.lineTo(Math.pow(1 - t, 2) * x0 + 2 * (1 - t) * t * x1 + t * t * x2 + Math.random() * this.shake - this.shake / 2, 187 | Math.pow(1 - t, 2) * y0 + 2 * (1 - t) * t * y1 + t * t * y2 + Math.random() * this.shake - this.shake / 2); 188 | } 189 | this._setXY(x2 + Math.random() * this.shake - this.shake / 2, 190 | y2 + Math.random() * this.shake - this.shake / 2); 191 | this.context.lineTo(this.x, this.y); 192 | }, 193 | 194 | _distance: function(x0, y0, x1, y1) { 195 | var dx = x1 - x0, 196 | dy = y1 - y0; 197 | return Math.sqrt(dx * dx + dy * dy); 198 | }, 199 | 200 | _setXY: function(x, y) { 201 | this.prevX = this.x; 202 | this.prevY = this.y; 203 | this.x = x; 204 | this.y = y; 205 | } 206 | 207 | } 208 | 209 | if (typeof define === "function" && define.amd) { 210 | define(shaky); 211 | } else { 212 | window.shaky = shaky; 213 | } 214 | 215 | }()); 216 | -------------------------------------------------------------------------------- /shakydemo.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var s = shaky.create("canvas"); 3 | s.setSize(window.innerWidth, window.innerHeight); 4 | 5 | // squares(); 6 | // lines(); 7 | // anim(); 8 | // arc(); 9 | // circle(); 10 | // ellipse(); 11 | // quadratic(); 12 | // bezier(); 13 | // segSizeShake(); 14 | hatch(); 15 | 16 | function squares() { 17 | for(var x = 10; x < s.width - 50; x += 60) { 18 | for(var y = 10; y < s.height - 50; y += 60) { 19 | s.strokeRect(x, y, 50, 50); 20 | } 21 | } 22 | } 23 | 24 | function lines() { 25 | s.beginPath(); 26 | for(var y = 0; y < s.height; y += 20) { 27 | s.moveTo(20, y); 28 | s.lineTo(s.width - 20, y); 29 | } 30 | s.stroke(); 31 | } 32 | 33 | function segSizeShake() { 34 | for(x = 6; x < s.width; x += 50) 35 | for(var y = 6; y < s.height; y += 50) { 36 | s.shake = x * .01; 37 | s.segSize = (s.height - y) * .01 + 1; 38 | s.strokeRect(x, y, 45, 45); 39 | } 40 | } 41 | 42 | function anim() { 43 | s.segSize = 10; 44 | s.shake = 5; 45 | animate(); 46 | function animate() { 47 | s.clear(); 48 | s.strokeRect(s.width / 2 - 50, s.height / 2 - 50, 100, 100); 49 | requestAnimationFrame(animate); 50 | } 51 | } 52 | 53 | function arc() { 54 | for(var x = 100; x < s.width - 50; x += 100) { 55 | for(var y = 100; y < s.height - 50; y += 100) { 56 | s.beginPath(); 57 | s.arc(x, y, 40, Math.random() * Math.PI * 2, Math.random() * Math.PI * 2, false); 58 | s.stroke(); 59 | } 60 | } 61 | } 62 | 63 | function circle() { 64 | s.segSize = 20; 65 | s.segSize = 10; 66 | s.shake = 5; 67 | for(var x = 100; x < s.width - 50; x += 100) { 68 | for(var y = 100; y < s.height - 50; y += 100) { 69 | s.strokeCircle(x, y, 40); 70 | } 71 | } 72 | } 73 | 74 | function ellipse() { 75 | s.segSize = 20; 76 | s.segSize = 10; 77 | s.shake = 5; 78 | for(var x = 100; x < s.width - 50; x += 100) { 79 | for(var y = 100; y < s.height - 50; y += 100) { 80 | s.strokeEllipse(x, y, Math.random() * 50 + 10, Math.random() * 50 + 10); 81 | } 82 | } 83 | } 84 | 85 | function quadratic() { 86 | document.body.addEventListener("mousemove", function(event) { 87 | s.clear(); 88 | s.beginPath(); 89 | s.moveTo(0, s.height / 2); 90 | s.quadraticCurveTo(event.clientX, event.clientY, s.width, s.height / 2); 91 | s.stroke(); 92 | }); 93 | } 94 | 95 | function bezier() { 96 | document.body.addEventListener("mousemove", function(event) { 97 | s.clear(); 98 | s.beginPath(); 99 | s.moveTo(0, s.height / 2); 100 | s.bezierCurveTo(event.clientX, event.clientY, 101 | s.width - event.clientX, s.height - event.clientY, 102 | s.width, s.height / 2); 103 | s.stroke(); 104 | 105 | }); 106 | } 107 | 108 | function hatch() { 109 | s.segSize = 10; 110 | s.shake = 0; 111 | var res = 100, 112 | div = res / 20 113 | for(var i = 0; i < s.width; i += res) { 114 | for(var j = 0; j < s.height; j += res) { 115 | s.beginPath(); 116 | for(var y = j + div; y <= j + res / 2 - div; y += div) { 117 | s.moveTo(i - div, y); 118 | s.lineTo(i + res / 2 + div, y); 119 | } 120 | for(var x = i + res / 2 + div; x <= i + res - div; x += div) { 121 | s.moveTo(x, j - div); 122 | s.lineTo(x, j + res / 2 + div); 123 | } 124 | for(var y = j + res / 2 + div; y <= j + res - div; y += div) { 125 | s.moveTo(i + res / 2 - div, y); 126 | s.lineTo(i + res + div, y); 127 | } 128 | for(var x = i + div; x <= i + res / 2 - div; x += div) { 129 | s.moveTo(x, j + res / 2 - div); 130 | s.lineTo(x, j + res + div); 131 | } 132 | s.stroke(); 133 | s.shake += .03; 134 | } 135 | } 136 | } 137 | 138 | }()); -------------------------------------------------------------------------------- /shakydemorequire.js: -------------------------------------------------------------------------------- 1 | require(["shaky"], function(shaky) { 2 | var s = shaky.create("canvas"); 3 | s.setSize(window.innerWidth, window.innerHeight); 4 | 5 | // squares(); 6 | // lines(); 7 | // anim(); 8 | // arc(); 9 | // circle(); 10 | // ellipse(); 11 | // quadratic(); 12 | // bezier(); 13 | // segSizeShake(); 14 | hatch(); 15 | 16 | 17 | function squares() { 18 | for(var x = 10; x < s.width - 50; x += 60) { 19 | for(var y = 10; y < s.height - 50; y += 60) { 20 | s.strokeRect(x, y, 50, 50); 21 | } 22 | } 23 | } 24 | 25 | function lines() { 26 | s.beginPath(); 27 | for(var y = 0; y < s.height; y += 20) { 28 | s.moveTo(20, y); 29 | s.lineTo(s.width - 20, y); 30 | } 31 | s.stroke(); 32 | } 33 | 34 | function segSizeShake() { 35 | for(x = 6; x < s.width; x += 50) 36 | for(var y = 6; y < s.height; y += 50) { 37 | s.shake = x * .01; 38 | s.segSize = (s.height - y) * .01 + 1; 39 | s.strokeRect(x, y, 45, 45); 40 | } 41 | } 42 | 43 | function anim() { 44 | s.segSize = 10; 45 | s.shake = 5; 46 | animate(); 47 | function animate() { 48 | s.clear(); 49 | s.strokeRect(s.width / 2 - 50, s.height / 2 - 50, 100, 100); 50 | requestAnimationFrame(animate); 51 | } 52 | } 53 | 54 | function arc() { 55 | for(var x = 100; x < s.width - 50; x += 100) { 56 | for(var y = 100; y < s.height - 50; y += 100) { 57 | s.beginPath(); 58 | s.arc(x, y, 40, Math.random() * Math.PI * 2, Math.random() * Math.PI * 2, false); 59 | s.stroke(); 60 | } 61 | } 62 | } 63 | 64 | function circle() { 65 | s.segSize = 20; 66 | s.segSize = 10; 67 | s.shake = 5; 68 | for(var x = 100; x < s.width - 50; x += 100) { 69 | for(var y = 100; y < s.height - 50; y += 100) { 70 | s.strokeCircle(x, y, 40); 71 | } 72 | } 73 | } 74 | 75 | function ellipse() { 76 | s.segSize = 20; 77 | s.segSize = 10; 78 | s.shake = 5; 79 | for(var x = 100; x < s.width - 50; x += 100) { 80 | for(var y = 100; y < s.height - 50; y += 100) { 81 | s.strokeEllipse(x, y, Math.random() * 50 + 10, Math.random() * 50 + 10); 82 | } 83 | } 84 | } 85 | 86 | function quadratic() { 87 | document.body.addEventListener("mousemove", function(event) { 88 | s.clear(); 89 | s.beginPath(); 90 | s.moveTo(0, s.height / 2); 91 | s.quadraticCurveTo(event.clientX, event.clientY, s.width, s.height / 2); 92 | s.stroke(); 93 | }); 94 | } 95 | 96 | function bezier() { 97 | document.body.addEventListener("mousemove", function(event) { 98 | s.clear(); 99 | s.beginPath(); 100 | s.moveTo(0, s.height / 2); 101 | s.bezierCurveTo(event.clientX, event.clientY, 102 | s.width - event.clientX, s.height - event.clientY, 103 | s.width, s.height / 2); 104 | s.stroke(); 105 | 106 | }); 107 | } 108 | 109 | function hatch() { 110 | s.segSize = 10; 111 | s.shake = 0; 112 | var res = 100, 113 | div = res / 20 114 | for(var i = 0; i < s.width; i += res) { 115 | for(var j = 0; j < s.height; j += res) { 116 | s.beginPath(); 117 | for(var y = j + div; y <= j + res / 2 - div; y += div) { 118 | s.moveTo(i - div, y); 119 | s.lineTo(i + res / 2 + div, y); 120 | } 121 | for(var x = i + res / 2 + div; x <= i + res - div; x += div) { 122 | s.moveTo(x, j - div); 123 | s.lineTo(x, j + res / 2 + div); 124 | } 125 | for(var y = j + res / 2 + div; y <= j + res - div; y += div) { 126 | s.moveTo(i + res / 2 - div, y); 127 | s.lineTo(i + res + div, y); 128 | } 129 | for(var x = i + div; x <= i + res / 2 - div; x += div) { 130 | s.moveTo(x, j + res / 2 - div); 131 | s.lineTo(x, j + res + div); 132 | } 133 | s.stroke(); 134 | s.shake += .03; 135 | } 136 | } 137 | } 138 | }); --------------------------------------------------------------------------------