From 350f7b7496e41998600b5a5f2b055fe219f1eb58 Mon Sep 17 00:00:00 2001 From: Eric Rowell Date: Thu, 5 Apr 2012 00:06:00 -0700 Subject: [PATCH] implemented stage.load() which allows you to deserialize a json string --- dist/kinetic-core.js | 80 +++++++++++++++++++++++++++++------- dist/kinetic-core.min.js | 6 +-- src/Node.js | 2 +- src/Shape.js | 2 +- src/Stage.js | 55 ++++++++++++++++++++----- src/shapes/Circle.js | 7 +++- src/shapes/Image.js | 2 + src/shapes/Polygon.js | 2 + src/shapes/Rect.js | 2 + src/shapes/RegularPolygon.js | 2 + src/shapes/Star.js | 2 + src/shapes/Text.js | 2 + tests/js/unitTests.js | 11 +++++ 13 files changed, 145 insertions(+), 30 deletions(-) diff --git a/dist/kinetic-core.js b/dist/kinetic-core.js index 89500a55..ca812133 100644 --- a/dist/kinetic-core.js +++ b/dist/kinetic-core.js @@ -3,7 +3,7 @@ * http://www.kineticjs.com/ * Copyright 2012, Eric Rowell * Licensed under the MIT or GPL Version 2 licenses. - * Date: Apr 04 2012 + * Date: Apr 05 2012 * * Copyright (C) 2011 - 2012 by Eric Rowell * @@ -210,7 +210,7 @@ Kinetic.Node = function(config) { } // used for serialization - Kinetic.GlobalObject.jsonProps.call(this, ['alpha', 'centerOffset', 'dragBounds', 'dragConstraint', '_draggable', 'id', 'listening', 'name', 'nodeType', 'rotation', 'scale', 'visible', 'x', 'y']); + Kinetic.GlobalObject.jsonProps.call(this, ['alpha', 'centerOffset', 'dragBounds', 'dragConstraint', '_draggable', 'listening', 'name', 'nodeType', 'rotation', 'scale', 'visible', 'x', 'y']); }; /* * Node methods @@ -1121,8 +1121,8 @@ Kinetic.Stage.prototype = { * serialize stage and children as JSON object */ toJSON: function() { - var go = Kinetic.GlobalObject; - + var go = Kinetic.GlobalObject; + function addNode(node) { var obj = {}; @@ -1133,23 +1133,58 @@ Kinetic.Stage.prototype = { } } - if(node.nodeType === 'Shape') { - } - else { - obj.children = []; + if(node.nodeType !== 'Shape') { + obj._children = []; var children = node.getChildren(); for(var n = 0; n < children.length; n++) { var child = children[n]; - - obj.children.push(addNode(child)); + obj._children.push(addNode(child)); } } return obj; } - var obj = addNode(this); + return JSON.stringify(addNode(this)); + }, + /** + * load stage with JSON string + */ + load: function(json) { + function loadNode(node, obj) { + // copy properties over + for(var key in obj) { + node[key] = obj[key]; + } - return obj; + var children = obj._children; + if(children !== undefined) { + for(var n = 0; n < children.length; n++) { + var child = children[n]; + var type; + + // determine type + if(child.nodeType === 'Shape') { + // add custom shape + if(child.shapeType === undefined) { + type = 'Shape'; + } + // add standard shape + else { + type = child.shapeType; + } + } + else { + type = child.nodeType; + } + + var no = new Kinetic[type]({}); + node.add(no); + loadNode(no, child); + } + } + } + loadNode(this, JSON.parse(json)); + this.draw(); }, /** * remove layer from stage @@ -1899,7 +1934,7 @@ Kinetic.Shape = function(config) { this.drawFunc = config.drawFunc; // used for serialization - Kinetic.GlobalObject.jsonProps.call(this, ['fill', 'stroke', 'strokeWidth', 'detectionType']); + Kinetic.GlobalObject.jsonProps.call(this, ['fill', 'stroke', 'strokeWidth', 'detectionType', 'shapeType']); // call super constructor Kinetic.Node.apply(this, [config]); @@ -2101,6 +2136,8 @@ Kinetic.GlobalObject.extend(Kinetic.Shape, Kinetic.Node); * @param {Object} config */ Kinetic.Rect = function(config) { + this.shapeType = "Rect"; + config.drawFunc = function() { var context = this.getContext(); context.beginPath(); @@ -2175,15 +2212,20 @@ Kinetic.GlobalObject.extend(Kinetic.Rect, Kinetic.Shape); * @param {Object} config */ Kinetic.Circle = function(config) { + this.shapeType = "Circle"; + config.drawFunc = function() { var canvas = this.getCanvas(); var context = this.getContext(); - context.beginPath(); + context.beginPath(); this.applyLineJoin(); context.arc(0, 0, this.radius, 0, Math.PI * 2, true); context.closePath(); this.fillStroke(); }; + // used for serialization + Kinetic.GlobalObject.jsonProps.call(this, ['radius']); + // call super constructor Kinetic.Shape.apply(this, [config]); }; @@ -2219,6 +2261,8 @@ Kinetic.GlobalObject.extend(Kinetic.Circle, Kinetic.Shape); * @param {Object} config */ Kinetic.Image = function(config) { + this.shapeType = "Image"; + // defaults if(config.width === undefined) { config.width = config.image.width; @@ -2315,6 +2359,8 @@ Kinetic.GlobalObject.extend(Kinetic.Image, Kinetic.Shape); * @param {Object} config */ Kinetic.Polygon = function(config) { + this.shapeType = "Polygon"; + config.drawFunc = function() { var context = this.getContext(); context.beginPath(); @@ -2361,6 +2407,8 @@ Kinetic.GlobalObject.extend(Kinetic.Polygon, Kinetic.Shape); * @param {Object} config */ Kinetic.RegularPolygon = function(config) { + this.shapeType = "RegularPolygon"; + config.drawFunc = function() { var context = this.getContext(); context.beginPath(); @@ -2436,6 +2484,8 @@ Kinetic.GlobalObject.extend(Kinetic.RegularPolygon, Kinetic.Shape); * @param {Object} config */ Kinetic.Star = function(config) { + this.shapeType = "Star"; + config.drawFunc = function() { var context = this.getContext(); context.beginPath(); @@ -2511,6 +2561,8 @@ Kinetic.GlobalObject.extend(Kinetic.Star, Kinetic.Shape); * @param {Object} config */ Kinetic.Text = function(config) { + this.shapeType = "Text"; + /* * defaults */ diff --git a/dist/kinetic-core.min.js b/dist/kinetic-core.min.js index e9811aa7..44c9c099 100644 --- a/dist/kinetic-core.min.js +++ b/dist/kinetic-core.min.js @@ -3,7 +3,7 @@ * http://www.kineticjs.com/ * Copyright 2012, Eric Rowell * Licensed under the MIT or GPL Version 2 licenses. - * Date: Apr 04 2012 + * Date: Apr 05 2012 * * Copyright (C) 2011 - 2012 by Eric Rowell * @@ -25,5 +25,5 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -var Kinetic={};Kinetic.GlobalObject={stages:[],idCounter:0,animations:[],animIdCounter:0,frame:{time:0,timeDiff:0,lastTime:0},drag:{moving:!1,node:undefined,offset:{x:0,y:0}},jsonProps:function(a){this.jsonProps===undefined?this.jsonProps=a:this.jsonProps=this.jsonProps.concat(a)},arrayHas:function(a,b){for(var c=0;c0){this._updateFrameObject(),this._runFrames();var a=this;requestAnimFrame(function(){a._animationLoop()})}else this.frame.lastTime=0},_handleAnimation:function(){var a=this;this.animations.length>0?a._animationLoop():this.frame.lastTime=0}},window.requestAnimFrame=function(a){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(a){window.setTimeout(a,1e3/60)}}(),Kinetic.Node=function(a){this.visible=!0,this.listening=!0,this.name=undefined,this.alpha=1,this.x=0,this.y=0,this.scale={x:1,y:1},this.rotation=0,this.centerOffset={x:0,y:0},this.eventListeners={},this.dragConstraint="none",this.dragBounds={},this._draggable=!1;if(a)for(var b in a)switch(b){case"draggable":this.draggable(a[b]);break;case"listen":this.listen(a[b]);break;case"rotationDeg":this.rotation=a[b]*Math.PI/180;break;default:this[b]=a[b]}this.centerOffset.x===undefined&&(this.centerOffset.x=0),this.centerOffset.y===undefined&&(this.centerOffset.y=0),Kinetic.GlobalObject.jsonProps.call(this,["alpha","centerOffset","dragBounds","dragConstraint","_draggable","id","listening","name","nodeType","rotation","scale","visible","x","y"])},Kinetic.Node.prototype={on:function(a,b){var c=a.split(" ");for(var d=0;d1?g[1]:"";this.eventListeners[h]||(this.eventListeners[h]=[]),this.eventListeners[h].push({name:i,handler:b})}},off:function(a){var b=a.split(" ");for(var c=0;c1){var h=f[1];for(var i=0;i0&&f[0].getLevel()<=a&&e(f)}var a=this.getLevel(),b=this.getStage(),c=this,d=0;return c.nodeType!=="Stage"&&e(c.getStage().getChildren()),d},getLevel:function(){var a=0,b=this.parent;while(b)a++,b=b.parent;return a},setScale:function(a,b){b?(this.scale.x=a,this.scale.y=b):(this.scale.x=a,this.scale.y=a)},getScale:function(){return this.scale},setPosition:function(a,b){this.x=a,this.y=b},getPosition:function(){return{x:this.x,y:this.y}},getAbsolutePosition:function(){return this.getAbsoluteTransform().getTranslation()},move:function(a,b){this.x+=a,this.y+=b},setRotation:function(a){this.rotation=a},setRotationDeg:function(a){this.rotation=a*Math.PI/180},getRotation:function(){return this.rotation},getRotationDeg:function(){return this.rotation*180/Math.PI},rotate:function(a){this.rotation+=a},rotateDeg:function(a){this.rotation+=a*Math.PI/180},listen:function(a){this.listening=a},moveToTop:function(){var a=this.index;this.parent.children.splice(a,1),this.parent.children.push(this),this.parent._setChildrenIndices()},moveUp:function(){var a=this.index;this.parent.children.splice(a,1),this.parent.children.splice(a+1,0,this),this.parent._setChildrenIndices()},moveDown:function(){var a=this.index;a>0&&(this.parent.children.splice(a,1),this.parent.children.splice(a-1,0,this),this.parent._setChildrenIndices())},moveToBottom:function(){var a=this.index;this.parent.children.splice(a,1),this.parent.children.unshift(this),this.parent._setChildrenIndices()},setZIndex:function(a){var b=this.index;this.parent.children.splice(b,1),this.parent.children.splice(a,0,this),this.parent._setChildrenIndices()},setAlpha:function(a){this.alpha=a},getAlpha:function(){return this.alpha},getAbsoluteAlpha:function(){var a=1,b=this;while(b.nodeType!=="Stage")a*=b.alpha,b=b.parent;return a},draggable:function(a){this.draggable!==a&&(a?this._initDrag():this._dragCleanup(),this._draggable=a)},isDragging:function(){var a=Kinetic.GlobalObject;return a.drag.node!==undefined&&a.drag.node.id===this.id&&a.drag.moving},moveTo:function(a){var b=this.parent;b.children.splice(this.index,1),b._setChildrenIndices(),a.children.push(this),this.index=a.children.length-1,this.parent=a,a._setChildrenIndices(),this.name&&(b.childrenNames[this.name]=undefined,a.childrenNames[this.name]=this)},getParent:function(){return this.parent},getLayer:function(){return this.nodeType==="Layer"?this:this.getParent().getLayer()},getStage:function(){return this.nodeType==="Stage"?this:this.getParent().getStage()},getName:function(){return this.name},setCenterOffset:function(a,b){this.centerOffset.x=a,this.centerOffset.y=b},getCenterOffset:function(){return this.centerOffset},transitionTo:function(a){var b=this.nodeType==="Stage"?this:this.getLayer(),c=this,d=Kinetic.GlobalObject,e=new Kinetic.Transition(this,a),f={func:function(){e.onEnterFrame()},node:b};return d.addAnimation(f),e.tweens[0].onFinished=function(){d.removeAnimation(f.id),a.callback!==undefined&&a.callback()},e.start(),d._handleAnimation(),e},setDragConstraint:function(a){this.dragConstraint=a},getDragConstraint:function(){return this.dragConstraint},setDragBounds:function(a){this.dragBounds=a},getDragBounds:function(){return this.dragBounds},getAbsoluteTransform:function(){var a=new Kinetic.Transform,b=[],c=this.parent;b.unshift(this);while(c)b.unshift(c),c=c.parent;for(var d=0;d0)this.remove(this.children[0])},_remove:function(a){this.children[a.index].id==a.id&&(a.name!==undefined&&(this.childrenNames[a.name]=undefined),this.children.splice(a.index,1),this._setChildrenIndices(),a=undefined)},_drawChildren:function(){var a=this.children;for(var b=0;b=0;d--){var e=c[d];if(e.listening)if(e.nodeType==="Shape"){var f=this._detectEvent(e,b);if(f)return!0}else{var f=this._traverseChildren(e,b);if(f)return!0}}return!1},_handleStageEvent:function(a){var b=Kinetic.GlobalObject;a||(a=window.event),this._setMousePosition(a),this._setTouchPosition(a),this.pathLayer.clear(),this.targetFound=!1;var c=!1;for(var d=this.children.length-1;d>=0;d--){var e=this.children[d];e.visible&&d>=0&&e.listening&&this._traverseChildren(e,a)&&(d=-1,c=!0)}!c&&this.mouseoutShape&&(this.mouseoutShape._handleEvents("onmouseout",a),this.mouseoutShape=undefined)},_listen:function(){var a=this;this.content.addEventListener("mousedown",function(b){a.mouseDown=!0,a._handleStageEvent(b)},!1),this.content.addEventListener("mousemove",function(b){a.mouseUp=!1,a.mouseDown=!1,a._handleStageEvent(b)},!1),this.content.addEventListener("mouseup",function(b){a.mouseUp=!0,a.mouseDown=!1,a._handleStageEvent(b),a.clickStart=!1},!1),this.content.addEventListener("mouseover",function(b){a._handleStageEvent(b)},!1),this.content.addEventListener("mouseout",function(b){var c=a.targetShape;c&&(c._handleEvents("onmouseout",b),a.targetShape=undefined),a.mousePos=undefined},!1),this.content.addEventListener("touchstart",function(b){b.preventDefault(),a.touchStart=!0,a._handleStageEvent(b)},!1),this.content.addEventListener("touchmove",function(b){b.preventDefault(),a._handleStageEvent(b)},!1),this.content.addEventListener("touchend",function(b){b.preventDefault(),a.touchEnd=!0,a._handleStageEvent(b)},!1)},_setMousePosition:function(a){var b=a.offsetX||a.clientX-this._getContentPosition().left+window.pageXOffset,c=a.offsetY||a.clientY-this._getContentPosition().top+window.pageYOffset;this.mousePos={x:b,y:c}},_setTouchPosition:function(a){if(a.touches!==undefined&&a.touches.length===1){var b=a.touches[0],c=b.clientX-this._getContentPosition().left+window.pageXOffset,d=b.clientY-this._getContentPosition().top+window.pageYOffset;this.touchPos={x:c,y:d}}},_getContentPosition:function(){var a=this.content,b=0,c=0;while(a&&a.tagName!=="BODY")b+=a.offsetTop-a.scrollTop,c+=a.offsetLeft-a.scrollLeft,a=a.offsetParent;return{top:b,left:c}},_modifyPathContext:function(a){a.stroke=function(){},a.fill=function(){},a.fillRect=function(b,c,d,e){a.rect(b,c,d,e)},a.strokeRect=function(b,c,d,e){a.rect(b,c,d,e)},a.drawImage=function(){},a.fillText=function(){},a.strokeText=function(){}},_endDrag:function(a){var b=Kinetic.GlobalObject;b.drag.node&&b.drag.moving&&(b.drag.moving=!1,b.drag.node._handleEvents("ondragend",a)),b.drag.node=undefined},_prepareDrag:function(){var a=this;this.onContent("mousemove touchmove",function(b){var c=Kinetic.GlobalObject,d=c.drag.node;if(d){var e=a.getUserPosition(),f=d.dragConstraint,g=d.dragBounds,h={x:e.x-c.drag.offset.x,y:e.y-c.drag.offset.y};g.left!==undefined&&h.xg.right&&(h.x=g.right),g.top!==undefined&&h.yg.bottom&&(h.y=g.bottom);var i=d.rotation,j={x:d.scale.x,y:d.scale.y};d.rotation=0,d.scale={x:1,y:1};var k=d.getAbsoluteTransform();k.invert(),k.translate(h.x,h.y),h={x:d.x+k.getTranslation().x,y:d.y+k.getTranslation().y},f==="horizontal"?h.y=d.y:f==="vertical"&&(h.x=d.x),d.setPosition(h.x,h.y),d.rotate(i),d.scale={x:j.x,y:j.y},c.drag.node.getLayer().draw(),c.drag.moving||(c.drag.moving=!0,c.drag.node._handleEvents("ondragstart",b)),c.drag.node._handleEvents("ondragmove",b)}},!1),this.onContent("mouseup touchend mouseout",function(b){a._endDrag(b)})},_buildDOM:function(){this.content.style.width=this.width+"px",this.content.style.height=this.height+"px",this.content.style.position="relative",this.content.style.display="inline-block",this.content.className="kineticjs-content",this.container.appendChild(this.content),this.bufferLayer=new Kinetic.Layer({name:"bufferLayer"}),this.pathLayer=new Kinetic.Layer({name:"pathLayer"}),this.bufferLayer.parent=this,this.pathLayer.parent=this,this._modifyPathContext(this.pathLayer.context),this.bufferLayer.getCanvas().style.display="none",this.pathLayer.getCanvas().style.display="none",this.bufferLayer.canvas.width=this.width,this.bufferLayer.canvas.height=this.height,this.bufferLayer.canvas.className="kineticjs-buffer-layer",this.content.appendChild(this.bufferLayer.canvas),this.pathLayer.canvas.width=this.width,this.pathLayer.canvas.height=this.height,this.pathLayer.canvas.className="kineticjs-path-layer",this.content.appendChild(this.pathLayer.canvas)}},Kinetic.GlobalObject.extend(Kinetic.Stage,Kinetic.Container),Kinetic.GlobalObject.extend(Kinetic.Stage,Kinetic.Node),Kinetic.Layer=function(a){this.nodeType="Layer",this.canvas=document.createElement("canvas"),this.context=this.canvas.getContext("2d"),this.canvas.style.position="absolute",Kinetic.GlobalObject.jsonProps.call(this,[]),Kinetic.Container.apply(this,[]),Kinetic.Node.apply(this,[a])},Kinetic.Layer.prototype={draw:function(){this._draw()},clear:function(){var a=this.getContext(),b=this.getCanvas();a.clearRect(0,0,b.width,b.height)},getCanvas:function(){return this.canvas},getContext:function(){return this.context},add:function(a){this._add(a)},remove:function(a){this._remove(a)},_draw:function(){this.clear(),this.visible&&this._drawChildren()}},Kinetic.GlobalObject.extend(Kinetic.Layer,Kinetic.Container),Kinetic.GlobalObject.extend(Kinetic.Layer,Kinetic.Node),Kinetic.Group=function(a){this.nodeType="Group",Kinetic.GlobalObject.jsonProps.call(this,[]),Kinetic.Container.apply(this,[]),Kinetic.Node.apply(this,[a])},Kinetic.Group.prototype={add:function(a){this._add(a)},remove:function(a){this._remove(a)},_draw:function(){this.visible&&this._drawChildren()}},Kinetic.GlobalObject.extend(Kinetic.Group,Kinetic.Container),Kinetic.GlobalObject.extend(Kinetic.Group,Kinetic.Node),Kinetic.Shape=function(a){this.nodeType="Shape",this.data=[];if(a.stroke!==undefined||a.strokeWidth!==undefined)a.stroke===undefined?a.stroke="black":a.strokeWidth===undefined&&(a.strokeWidth=2);this.detectionType="path",this.drawFunc=a.drawFunc,Kinetic.GlobalObject.jsonProps.call(this,["fill","stroke","strokeWidth","detectionType"]),Kinetic.Node.apply(this,[a])},Kinetic.Shape.prototype={getContext:function(){return this.tempLayer.getContext()},getCanvas:function(){return this.tempLayer.getCanvas()},fillStroke:function(){var a=this.getContext();this.fill!==undefined&&(a.fillStyle=this.fill,a.fill()),this.stroke!==undefined&&(a.lineWidth=this.strokeWidth===undefined?1:this.strokeWidth,a.strokeStyle=this.stroke,a.stroke())},applyLineJoin:function(){var a=this.getContext();this.lineJoin!==undefined&&(a.lineJoin=this.lineJoin)},setFill:function(a){this.fill=a},getFill:function(){return this.fill},setStroke:function(a){this.stroke=a},getStroke:function(){return this.stroke},setLineJoin:function(a){this.lineJoin=a},getLineJoin:function(){return this.lineJoin},setStrokeWidth:function(a){this.strokeWidth=a},getStrokeWidth:function(){return this.strokeWidth},setDrawFunc:function(a){this.drawFunc=a},save:function(){var a=this.getStage(),b=a.width,c=a.height,d=a.bufferLayer,e=d.getContext();d.clear(),this._draw(d);var f=e.getImageData(0,0,b,c);this.data=f.data},_draw:function(a){if(this.visible){var b=a.getStage(),c=a.getContext(),d=[],e=this.parent;d.unshift(this);while(e)d.unshift(e),e=e.parent;c.save();for(var f=0;fthis.getDuration()?this.looping?(this.rewind(a-this._duration),this.update(),this.broadcastMessage("onLooped",{target:this,type:"onLooped"})):(this._time=this._duration,this.update(),this.stop(),this.broadcastMessage("onFinished",{target:this,type:"onFinished"})):a<0?(this.rewind(),this.update()):(this._time=a,this.update())},getTime:function(){return this._time},setDuration:function(a){this._duration=a===null||a<=0?1e5:a},getDuration:function(){return this._duration},setPosition:function(a){this.prevPos=this._pos,this.propFunc(a),this._pos=a,this.broadcastMessage("onChanged",{target:this,type:"onChanged" -})},getPosition:function(a){return a===undefined&&(a=this._time),this.func(a,this.begin,this._change,this._duration)},setFinish:function(a){this._change=a-this.begin},getFinish:function(){return this.begin+this._change},start:function(){this.rewind(),this.startEnterFrame(),this.broadcastMessage("onStarted",{target:this,type:"onStarted"})},rewind:function(a){this.stop(),this._time=a===undefined?0:a,this.fixTime(),this.update()},fforward:function(){this._time=this._duration,this.fixTime(),this.update()},update:function(){this.setPosition(this.getPosition(this._time))},startEnterFrame:function(){this.stopEnterFrame(),this.isPlaying=!0,this.onEnterFrame()},onEnterFrame:function(){this.isPlaying&&this.nextFrame()},nextFrame:function(){this.setTime((this.getTimer()-this._startTime)/1e3)},stop:function(){this.stopEnterFrame(),this.broadcastMessage("onStopped",{target:this,type:"onStopped"})},stopEnterFrame:function(){this.isPlaying=!1},continueTo:function(a,b){this.begin=this._pos,this.setFinish(a),this._duration!=undefined&&this.setDuration(b),this.start()},resume:function(){this.fixTime(),this.startEnterFrame(),this.broadcastMessage("onResumed",{target:this,type:"onResumed"})},yoyo:function(){this.continueTo(this.begin,this._time)},addListener:function(a){return this.removeListener(a),this._listeners.push(a)},removeListener:function(a){var b=this._listeners,c=b.length;while(c--)if(b[c]==a)return b.splice(c,1),!0;return!1},broadcastMessage:function(){var a=[];for(var b=0;b0){this._updateFrameObject(),this._runFrames();var a=this;requestAnimFrame(function(){a._animationLoop()})}else this.frame.lastTime=0},_handleAnimation:function(){var a=this;this.animations.length>0?a._animationLoop():this.frame.lastTime=0}},window.requestAnimFrame=function(a){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(a){window.setTimeout(a,1e3/60)}}(),Kinetic.Node=function(a){this.visible=!0,this.listening=!0,this.name=undefined,this.alpha=1,this.x=0,this.y=0,this.scale={x:1,y:1},this.rotation=0,this.centerOffset={x:0,y:0},this.eventListeners={},this.dragConstraint="none",this.dragBounds={},this._draggable=!1;if(a)for(var b in a)switch(b){case"draggable":this.draggable(a[b]);break;case"listen":this.listen(a[b]);break;case"rotationDeg":this.rotation=a[b]*Math.PI/180;break;default:this[b]=a[b]}this.centerOffset.x===undefined&&(this.centerOffset.x=0),this.centerOffset.y===undefined&&(this.centerOffset.y=0),Kinetic.GlobalObject.jsonProps.call(this,["alpha","centerOffset","dragBounds","dragConstraint","_draggable","listening","name","nodeType","rotation","scale","visible","x","y"])},Kinetic.Node.prototype={on:function(a,b){var c=a.split(" ");for(var d=0;d1?g[1]:"";this.eventListeners[h]||(this.eventListeners[h]=[]),this.eventListeners[h].push({name:i,handler:b})}},off:function(a){var b=a.split(" ");for(var c=0;c1){var h=f[1];for(var i=0;i0&&f[0].getLevel()<=a&&e(f)}var a=this.getLevel(),b=this.getStage(),c=this,d=0;return c.nodeType!=="Stage"&&e(c.getStage().getChildren()),d},getLevel:function(){var a=0,b=this.parent;while(b)a++,b=b.parent;return a},setScale:function(a,b){b?(this.scale.x=a,this.scale.y=b):(this.scale.x=a,this.scale.y=a)},getScale:function(){return this.scale},setPosition:function(a,b){this.x=a,this.y=b},getPosition:function(){return{x:this.x,y:this.y}},getAbsolutePosition:function(){return this.getAbsoluteTransform().getTranslation()},move:function(a,b){this.x+=a,this.y+=b},setRotation:function(a){this.rotation=a},setRotationDeg:function(a){this.rotation=a*Math.PI/180},getRotation:function(){return this.rotation},getRotationDeg:function(){return this.rotation*180/Math.PI},rotate:function(a){this.rotation+=a},rotateDeg:function(a){this.rotation+=a*Math.PI/180},listen:function(a){this.listening=a},moveToTop:function(){var a=this.index;this.parent.children.splice(a,1),this.parent.children.push(this),this.parent._setChildrenIndices()},moveUp:function(){var a=this.index;this.parent.children.splice(a,1),this.parent.children.splice(a+1,0,this),this.parent._setChildrenIndices()},moveDown:function(){var a=this.index;a>0&&(this.parent.children.splice(a,1),this.parent.children.splice(a-1,0,this),this.parent._setChildrenIndices())},moveToBottom:function(){var a=this.index;this.parent.children.splice(a,1),this.parent.children.unshift(this),this.parent._setChildrenIndices()},setZIndex:function(a){var b=this.index;this.parent.children.splice(b,1),this.parent.children.splice(a,0,this),this.parent._setChildrenIndices()},setAlpha:function(a){this.alpha=a},getAlpha:function(){return this.alpha},getAbsoluteAlpha:function(){var a=1,b=this;while(b.nodeType!=="Stage")a*=b.alpha,b=b.parent;return a},draggable:function(a){this.draggable!==a&&(a?this._initDrag():this._dragCleanup(),this._draggable=a)},isDragging:function(){var a=Kinetic.GlobalObject;return a.drag.node!==undefined&&a.drag.node.id===this.id&&a.drag.moving},moveTo:function(a){var b=this.parent;b.children.splice(this.index,1),b._setChildrenIndices(),a.children.push(this),this.index=a.children.length-1,this.parent=a,a._setChildrenIndices(),this.name&&(b.childrenNames[this.name]=undefined,a.childrenNames[this.name]=this)},getParent:function(){return this.parent},getLayer:function(){return this.nodeType==="Layer"?this:this.getParent().getLayer()},getStage:function(){return this.nodeType==="Stage"?this:this.getParent().getStage()},getName:function(){return this.name},setCenterOffset:function(a,b){this.centerOffset.x=a,this.centerOffset.y=b},getCenterOffset:function(){return this.centerOffset},transitionTo:function(a){var b=this.nodeType==="Stage"?this:this.getLayer(),c=this,d=Kinetic.GlobalObject,e=new Kinetic.Transition(this,a),f={func:function(){e.onEnterFrame()},node:b};return d.addAnimation(f),e.tweens[0].onFinished=function(){d.removeAnimation(f.id),a.callback!==undefined&&a.callback()},e.start(),d._handleAnimation(),e},setDragConstraint:function(a){this.dragConstraint=a},getDragConstraint:function(){return this.dragConstraint},setDragBounds:function(a){this.dragBounds=a},getDragBounds:function(){return this.dragBounds},getAbsoluteTransform:function(){var a=new Kinetic.Transform,b=[],c=this.parent;b.unshift(this);while(c)b.unshift(c),c=c.parent;for(var d=0;d0)this.remove(this.children[0])},_remove:function(a){this.children[a.index].id==a.id&&(a.name!==undefined&&(this.childrenNames[a.name]=undefined),this.children.splice(a.index,1),this._setChildrenIndices(),a=undefined)},_drawChildren:function(){var a=this.children;for(var b=0;b=0;d--){var e=c[d];if(e.listening)if(e.nodeType==="Shape"){var f=this._detectEvent(e,b);if(f)return!0}else{var f=this._traverseChildren(e,b);if(f)return!0}}return!1},_handleStageEvent:function(a){var b=Kinetic.GlobalObject;a||(a=window.event),this._setMousePosition(a),this._setTouchPosition(a),this.pathLayer.clear(),this.targetFound=!1;var c=!1;for(var d=this.children.length-1;d>=0;d--){var e=this.children[d];e.visible&&d>=0&&e.listening&&this._traverseChildren(e,a)&&(d=-1,c=!0)}!c&&this.mouseoutShape&&(this.mouseoutShape._handleEvents("onmouseout",a),this.mouseoutShape=undefined)},_listen:function(){var a=this;this.content.addEventListener("mousedown",function(b){a.mouseDown=!0,a._handleStageEvent(b)},!1),this.content.addEventListener("mousemove",function(b){a.mouseUp=!1,a.mouseDown=!1,a._handleStageEvent(b)},!1),this.content.addEventListener("mouseup",function(b){a.mouseUp=!0,a.mouseDown=!1,a._handleStageEvent(b),a.clickStart=!1},!1),this.content.addEventListener("mouseover",function(b){a._handleStageEvent(b)},!1),this.content.addEventListener("mouseout",function(b){var c=a.targetShape;c&&(c._handleEvents("onmouseout",b),a.targetShape=undefined),a.mousePos=undefined},!1),this.content.addEventListener("touchstart",function(b){b.preventDefault(),a.touchStart=!0,a._handleStageEvent(b)},!1),this.content.addEventListener("touchmove",function(b){b.preventDefault(),a._handleStageEvent(b)},!1),this.content.addEventListener("touchend",function(b){b.preventDefault(),a.touchEnd=!0,a._handleStageEvent(b)},!1)},_setMousePosition:function(a){var b=a.offsetX||a.clientX-this._getContentPosition().left+window.pageXOffset,c=a.offsetY||a.clientY-this._getContentPosition().top+window.pageYOffset;this.mousePos={x:b,y:c}},_setTouchPosition:function(a){if(a.touches!==undefined&&a.touches.length===1){var b=a.touches[0],c=b.clientX-this._getContentPosition().left+window.pageXOffset,d=b.clientY-this._getContentPosition().top+window.pageYOffset;this.touchPos={x:c,y:d}}},_getContentPosition:function(){var a=this.content,b=0,c=0;while(a&&a.tagName!=="BODY")b+=a.offsetTop-a.scrollTop,c+=a.offsetLeft-a.scrollLeft,a=a.offsetParent;return{top:b,left:c}},_modifyPathContext:function(a){a.stroke=function(){},a.fill=function(){},a.fillRect=function(b,c,d,e){a.rect(b,c,d,e)},a.strokeRect=function(b,c,d,e){a.rect(b,c,d,e)},a.drawImage=function(){},a.fillText=function(){},a.strokeText=function(){}},_endDrag:function(a){var b=Kinetic.GlobalObject;b.drag.node&&b.drag.moving&&(b.drag.moving=!1,b.drag.node._handleEvents("ondragend",a)),b.drag.node=undefined},_prepareDrag:function(){var a=this;this.onContent("mousemove touchmove",function(b){var c=Kinetic.GlobalObject,d=c.drag.node;if(d){var e=a.getUserPosition(),f=d.dragConstraint,g=d.dragBounds,h={x:e.x-c.drag.offset.x,y:e.y-c.drag.offset.y};g.left!==undefined&&h.xg.right&&(h.x=g.right),g.top!==undefined&&h.yg.bottom&&(h.y=g.bottom);var i=d.rotation,j={x:d.scale.x,y:d.scale.y};d.rotation=0,d.scale={x:1,y:1};var k=d.getAbsoluteTransform();k.invert(),k.translate(h.x,h.y),h={x:d.x+k.getTranslation().x,y:d.y+k.getTranslation().y},f==="horizontal"?h.y=d.y:f==="vertical"&&(h.x=d.x),d.setPosition(h.x,h.y),d.rotate(i),d.scale={x:j.x,y:j.y},c.drag.node.getLayer().draw(),c.drag.moving||(c.drag.moving=!0,c.drag.node._handleEvents("ondragstart",b)),c.drag.node._handleEvents("ondragmove",b)}},!1),this.onContent("mouseup touchend mouseout",function(b){a._endDrag(b)})},_buildDOM:function(){this.content.style.width=this.width+"px",this.content.style.height=this.height+"px",this.content.style.position="relative",this.content.style.display="inline-block",this.content.className="kineticjs-content",this.container.appendChild(this.content),this.bufferLayer=new Kinetic.Layer({name:"bufferLayer"}),this.pathLayer=new Kinetic.Layer({name:"pathLayer"}),this.bufferLayer.parent=this,this.pathLayer.parent=this,this._modifyPathContext(this.pathLayer.context),this.bufferLayer.getCanvas().style.display="none",this.pathLayer.getCanvas().style.display="none",this.bufferLayer.canvas.width=this.width,this.bufferLayer.canvas.height=this.height,this.bufferLayer.canvas.className="kineticjs-buffer-layer",this.content.appendChild(this.bufferLayer.canvas),this.pathLayer.canvas.width=this.width,this.pathLayer.canvas.height=this.height,this.pathLayer.canvas.className="kineticjs-path-layer",this.content.appendChild(this.pathLayer.canvas)}},Kinetic.GlobalObject.extend(Kinetic.Stage,Kinetic.Container),Kinetic.GlobalObject.extend(Kinetic.Stage,Kinetic.Node),Kinetic.Layer=function(a){this.nodeType="Layer",this.canvas=document.createElement("canvas"),this.context=this.canvas.getContext("2d"),this.canvas.style.position="absolute",Kinetic.GlobalObject.jsonProps.call(this,[]),Kinetic.Container.apply(this,[]),Kinetic.Node.apply(this,[a])},Kinetic.Layer.prototype={draw:function(){this._draw()},clear:function(){var a=this.getContext(),b=this.getCanvas();a.clearRect(0,0,b.width,b.height)},getCanvas:function(){return this.canvas},getContext:function(){return this.context},add:function(a){this._add(a)},remove:function(a){this._remove(a)},_draw:function(){this.clear(),this.visible&&this._drawChildren()}},Kinetic.GlobalObject.extend(Kinetic.Layer,Kinetic.Container),Kinetic.GlobalObject.extend(Kinetic.Layer,Kinetic.Node),Kinetic.Group=function(a){this.nodeType="Group",Kinetic.GlobalObject.jsonProps.call(this,[]),Kinetic.Container.apply(this,[]),Kinetic.Node.apply(this,[a])},Kinetic.Group.prototype={add:function(a){this._add(a)},remove:function(a){this._remove(a)},_draw:function(){this.visible&&this._drawChildren()}},Kinetic.GlobalObject.extend(Kinetic.Group,Kinetic.Container),Kinetic.GlobalObject.extend(Kinetic.Group,Kinetic.Node),Kinetic.Shape=function(a){this.nodeType="Shape",this.data=[];if(a.stroke!==undefined||a.strokeWidth!==undefined)a.stroke===undefined?a.stroke="black":a.strokeWidth===undefined&&(a.strokeWidth=2);this.detectionType="path",this.drawFunc=a.drawFunc,Kinetic.GlobalObject.jsonProps.call(this,["fill","stroke","strokeWidth","detectionType","shapeType"]),Kinetic.Node.apply(this,[a])},Kinetic.Shape.prototype={getContext:function(){return this.tempLayer.getContext()},getCanvas:function(){return this.tempLayer.getCanvas()},fillStroke:function(){var a=this.getContext();this.fill!==undefined&&(a.fillStyle=this.fill,a.fill()),this.stroke!==undefined&&(a.lineWidth=this.strokeWidth===undefined?1:this.strokeWidth,a.strokeStyle=this.stroke,a.stroke())},applyLineJoin:function(){var a=this.getContext();this.lineJoin!==undefined&&(a.lineJoin=this.lineJoin)},setFill:function(a){this.fill=a},getFill:function(){return this.fill},setStroke:function(a){this.stroke=a},getStroke:function(){return this.stroke},setLineJoin:function(a){this.lineJoin=a},getLineJoin:function(){return this.lineJoin},setStrokeWidth:function(a){this.strokeWidth=a},getStrokeWidth:function(){return this.strokeWidth},setDrawFunc:function(a){this.drawFunc=a},save:function(){var a=this.getStage(),b=a.width,c=a.height,d=a.bufferLayer,e=d.getContext();d.clear(),this._draw(d);var f=e.getImageData(0,0,b,c);this.data=f.data},_draw:function(a){if(this.visible){var b=a.getStage(),c=a.getContext(),d=[],e=this.parent;d.unshift(this);while(e)d.unshift(e),e=e.parent;c.save();for(var f=0;fthis.getDuration()?this.looping?(this.rewind(a-this._duration),this.update +(),this.broadcastMessage("onLooped",{target:this,type:"onLooped"})):(this._time=this._duration,this.update(),this.stop(),this.broadcastMessage("onFinished",{target:this,type:"onFinished"})):a<0?(this.rewind(),this.update()):(this._time=a,this.update())},getTime:function(){return this._time},setDuration:function(a){this._duration=a===null||a<=0?1e5:a},getDuration:function(){return this._duration},setPosition:function(a){this.prevPos=this._pos,this.propFunc(a),this._pos=a,this.broadcastMessage("onChanged",{target:this,type:"onChanged"})},getPosition:function(a){return a===undefined&&(a=this._time),this.func(a,this.begin,this._change,this._duration)},setFinish:function(a){this._change=a-this.begin},getFinish:function(){return this.begin+this._change},start:function(){this.rewind(),this.startEnterFrame(),this.broadcastMessage("onStarted",{target:this,type:"onStarted"})},rewind:function(a){this.stop(),this._time=a===undefined?0:a,this.fixTime(),this.update()},fforward:function(){this._time=this._duration,this.fixTime(),this.update()},update:function(){this.setPosition(this.getPosition(this._time))},startEnterFrame:function(){this.stopEnterFrame(),this.isPlaying=!0,this.onEnterFrame()},onEnterFrame:function(){this.isPlaying&&this.nextFrame()},nextFrame:function(){this.setTime((this.getTimer()-this._startTime)/1e3)},stop:function(){this.stopEnterFrame(),this.broadcastMessage("onStopped",{target:this,type:"onStopped"})},stopEnterFrame:function(){this.isPlaying=!1},continueTo:function(a,b){this.begin=this._pos,this.setFinish(a),this._duration!=undefined&&this.setDuration(b),this.start()},resume:function(){this.fixTime(),this.startEnterFrame(),this.broadcastMessage("onResumed",{target:this,type:"onResumed"})},yoyo:function(){this.continueTo(this.begin,this._time)},addListener:function(a){return this.removeListener(a),this._listeners.push(a)},removeListener:function(a){var b=this._listeners,c=b.length;while(c--)if(b[c]==a)return b.splice(c,1),!0;return!1},broadcastMessage:function(){var a=[];for(var b=0;b