-
Notifications
You must be signed in to change notification settings - Fork 96
/
canvas.min.js
35 lines (35 loc) · 9.87 KB
/
canvas.min.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
(function(window){!function(e){"use strict";var n,t=0,a=["moz","webkit","o","ms"];for(n=0;n<a.length&&!e.requestAnimationFrame;n+=1)e.requestAnimationFrame=e[a[n]+"RequestAnimationFrame"],e.cancelAnimationFrame=e[a[n]+"CancelAnimationFrame"]||e[a[n]+"CancelRequestAnimationFrame"];e.cancelAnimationFrame||(e.requestAnimationFrame?(a=e.requestAnimationFrame,t={},e.requestAnimationFrame=function(e){var i=n;return n+=1,t[i]=e,a(function(e){if(t.hasOwnProperty(i)){var n;try{t[i](e)}catch(e){n=e}finally{if(delete t[i],n)throw n}}}),i},e.cancelAnimationFrame=function(e){delete t[e]}):(e.requestAnimationFrame=function(n){var a=(new Date).getTime(),i=Math.max(t+16,a);return e.setTimeout(function(){n(t=i)},i-a)},e.cancelAnimationFrame=e.clearTimeout))}(this);!function(n){n.performance||(n.performance={now:function(){return+new Date}})}(this);window.CanvasRenderingContext2D&&(CanvasRenderingContext2D.prototype.reset=function(){this.setTransform(1,0,0,1,0,0)},CanvasRenderingContext2D.prototype.clear=function(preserveTransform){if(preserveTransform){this.save();this.reset()}this.clearRect(0,0,this.canvas.width,this.canvas.height);if(preserveTransform){this.restore()}});window.Canvas=class Canvas{constructor(){this.id=arguments[0];this.element=document.getElementById(this.id)?document.getElementById(this.id):document.createElement('canvas');this.element.id=this.id;this.renderer=this.element.ctx=this.element.getContext(arguments[3]||'2d');if(!document.getElementById(this.id))document.body.appendChild(this.element);this.width=this.element.width=arguments[1]||this.element.width;this.height=this.element.height=arguments[2]||this.element.height;if(arguments[1]==window.innerWidth&&arguments[2]==window.innerHeight)
window.addEventListener('resize',function(){this.width=this.element.width=window.innerWidth;this.height=this.element.height=window.innerHeight}.bind(this));if('ElementResizeEventListener' in window){this.element.addEventListener('resize',function(width,height){this.fireEvent('resize',width,height);this.width=width;this.height=height}.bind(this))}
this.eventListeners=new Map();this._HANDYOBJECT_={};this._rafid=0;this._running=!1;this._paused=!1;this._lastFrame=null;this.framerateLimit=Infinity;this._balanceFramerateMin=5;this._balanceFramerateMax=Infinity;this.canvasElements=[];this.reset=this.renderer.reset.bind(this.renderer);this.clear=this.renderer.clear.bind(this.renderer);this.drawWorkingFrame();this.fireEvent('init',this.renderer,this._HANDYOBJECT_,Canvas.now());return this}
on(event,fn){if(event=='draw'){this.element.ctx.clear()}
this.eventListeners.set(event,fn);return this}
fireEvent(event){let args=[];Array.prototype.push.apply(args,arguments);args.shift();if(this.eventListeners.has(event))this.eventListeners.get(event).apply(this,args)}
drawWorkingFrame(){this.drawFrame(function(renderer){if(renderer instanceof CanvasRenderingContext2D){renderer.clear();renderer.save();renderer.textAlign='center';renderer.font='30px Arial';renderer.fillText('Its Working!',this.width/2,this.height/2);renderer.restore()}})}
_loop(){if(!this._running)return;this._rafid=window.requestAnimationFrame(this._loop.bind(this),this.element);const now=Canvas.now();const delta=(now-this._lastFrame)/1000.0;if(1.0/delta>this.framerateLimit)return;this._lastFrame=now;if(!this._paused)this.fireEvent('update',this._HANDYOBJECT_,delta,Canvas.now());this.renderCanvasElements();this.fireEvent('draw',this.renderer,this._HANDYOBJECT_,delta,Canvas.now())}
drawFrame(fn){fn.bind(this)(this.renderer,this._HANDYOBJECT_)}
start(fn){if(this._running)return;this._running=!0;this._lastFrame=Canvas.now()-16;this.fireEvent('start',this.renderer,this._HANDYOBJECT_,Canvas.now());if(fn)fn.apply(this,[this.renderer,this._HANDYOBJECT_,Canvas.now()]);this._loop();return this}
stop(fn){if(!this._running)return;this._running=!1;this.fireEvent('stop',this.renderer,this._HANDYOBJECT_,Canvas.now());if(fn)fn.apply(this,[this.renderer,this._HANDYOBJECT_,Canvas.now()]);window.cancelAnimationFrame(this._rafid);return this}
pause(fn){if(this._paused)return;this._paused=!0;this.fireEvent('pause',this.renderer,this._HANDYOBJECT_,Canvas.now());if(fn)fn.apply(this,[this.renderer,this._HANDYOBJECT_,Canvas.now()]);return this}
resume(fn){if(!this._paused)return;this._paused=!1;this.fireEvent('resume',this.renderer,this._HANDYOBJECT_,Canvas.now());if(fn)fn.apply(this,[this.renderer,this._HANDYOBJECT_,Canvas.now()]);return this}
setFramerateLimit(limit){this.framerateLimit=limit}
balanceFramerate(bool,min,max){this.balanceFramerate=bool;if(min)this._balanceFramerateMin=min;if(max)this._balanceFramerateMax=max}
toImage(format){format=format||'png';return this.element.toDataURL('image/'+format)}
saveToStorage(key){key=key||'Canvas';window.localStorage.setItem('canvas-'+key,this.toImage())}
removeFromStorage(key){key=key||'Canvas';const base64=window.localStorage.getItem('canvas-'+key);if(!base64)return!1;window.localStorage.removeItem('canvas-'+key);return!0}
restoreFromStorage(key){key=key||'Canvas';const base64=window.localStorage.getItem('canvas-'+key);if(!base64)return!1;const image=new Image();image.src=base64;image.onload=function(){this.drawFrame(function(ctx){ctx.drawImage(image,0,0)})}.bind(this);return!0}
getObject(){return this._HANDYOBJECT_}
saveObject(key){key=key||'HO';window.localStorage.setItem('canvas-'+key,JSON.stringify(this.getObject()))}
loadObject(key){key=key||'HO';const handyObject=JSON.parse(window.localStorage.getItem('canvas-'+key));if(!handyObject||typeof handyObject!=='object')return!1;this._HANDYOBJECT_=handyObject;return this._HANDYOBJECT_}
removeSavedObject(key){key=key||'HO';const handyObject=window.localStorage.getItem('canvas-'+key);if(!handyObject)return!1;window.localStorage.removeItem('canvas-'+key);return!0}
addElement(canvasElement){this.canvasElements.push(canvasElement)}
removeElement(canvasElement){this.canvasElements.splice(this.canvasElements.indexOf(canvasElement),1)}
getElements(){return this.canvasElements}
renderCanvasElements(){const renderer=this.renderer;renderer.clear();if(this.canvasElements.length)renderer.clear();for(let element of this.canvasElements){if(element.animation){const ratio=(Canvas.now()-element.animation.start)/(element.animation.end-element.animation.start);if(ratio>=1){element.animation=!1}else{switch(element.animation.type){case 'move':element.x=Canvas.lerp(element.animation.from.x,element.animation.to.x,ratio);element.y=Canvas.lerp(element.animation.from.y,element.animation.to.y,ratio);break;case 'lineLength':element.lineLength=Canvas.lerp(element.animation.from.lineLength,element.animation.to.lineLength,ratio)}}}
switch(element.constructor.name){case 'CanvasImage':if(!element.element)continue;if(element.sourceX)
renderer.drawImage(element.element,element.sourceX,element.sourceY,element.sourceWidth,element.sourceHeight,element.x,element.y,element.width,element.height);else renderer.drawImage(element.element,element.x,element.y,element.width,element.height);break;case 'CanvasLine':renderer.save();renderer.beginPath();renderer.moveTo(element.from.x,element.from.y);renderer.lineTo(Canvas.lerp(element.from.x,element.to.x,element.lineLength),Canvas.lerp(element.from.y,element.to.y,element.lineLength));renderer.lineWidth=element.lineWidth;renderer.lineCap=element.lineCap;renderer.stroke();renderer.restore()}}}};Canvas.lerp=function(v1,v2,t){return(1-t)*v1+t*v2};Canvas.now=function(){if('performance' in window&&'now' in window.performance){return performance.now()}
return+new Date};Canvas.Vector=class Vector{constructor(){this.pos={};this.pos.x=arguments[0];this.pos.y=arguments[1];this.pos.z=arguments[2];this.rotation={};this.rotation.x=arguments[3];this.rotation.y=arguments[4];this.rotation.z=arguments[5]}
mult(vector){this.pos.x*=vector.pos.x;this.pos.y*=vector.pos.y;this.pos.z*=vector.pos.z;this.pos.x*=vector.rotation.x;this.pos.y*=vector.rotation.y;this.pos.z*=vector.rotation.z}
add(vector){this.pos.x+=vector.pos.x;this.pos.y+=vector.pos.y;this.pos.z+=vector.pos.z;this.pos.x+=vector.rotation.x;this.pos.y+=vector.rotation.y;this.pos.z+=vector.rotation.z}}
Canvas.Element=class Element{constructor(){const args=arguments[0]||{};this.x=typeof args.x!=='undefined'?args.x:null;this.y=typeof args.y!=='undefined'?args.y:null;this.width=typeof args.width!=='undefined'?args.width:null;this.height=typeof args.height!=='undefined'?args.height:null;this.rotation=typeof args.rotation!=='undefined'?args.rotation:null;this.animation=!1}
animate(){const type=arguments[0];const args=arguments[1];switch(type){case 'move':this.animation={type:type,from:{x:this.x,y:this.y},to:{x:args.x,y:args.y}};break;case 'lineLength':this.animation={type:type,from:{lineLength:this.lineLength},to:{lineLength:args.lineLength}};break;default:return!1};this.animation.start=Canvas.now();this.animation.end=this.animation.start+args.duration}};Canvas.Image=class CanvasImage extends Canvas.Element{constructor(){const args=arguments[0]||{};super(args);this.element=(function(){if(args.image)
return args.image;else{const image=new Image();image.src=args.url;return image}})();this.sourceX=args.sourceX||null;this.sourceY=args.sourceY||null;this.sourceWidth=args.sourceWidth||null;this.sourceHeight=args.sourceHeight||null;this.element.onload=function(){if(this.width){this.element.width=this.width}else this.width=this.element.width;if(this.height){this.element.height=this.height}else this.height=this.element.height;this.sourceX=args.sourceX||0;this.sourceY=args.sourceY||0;this.sourceWidth=args.sourceWidth||this.width;this.sourceHeight=args.sourceHeight||this.height;if(typeof arguments[1]=='function')arguments[1]()}.bind(this)}};Canvas.Line=class CanvasLine extends Canvas.Element{constructor(){const args=arguments[0]||{};super(args);this.from={x:args.from.x,y:args.from.y};this.to={x:args.to.x,y:args.to.y};this.lineWidth=args.lineWidth||2;this.lineCap=args.lineCap||'butt';this.lineLength=args.lineLength||0.5}}})(window)