diff --git a/README.md b/README.md index e3cb08d8..df190b99 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,4 @@ -#KineticJS - -[http://www.kineticjs.com](KineticJS) - -Greetings fellow webonauts! KineticJS is an HTML5 Canvas JavaScript library that extends the 2d context by enabling canvas interactivity for desktop and mobile applications. - -You can draw your own shapes or images using the existing canvas API, add event listeners to them, move them, scale them, and rotate them independently from other shapes to support high performance animations, even if your application uses thousands of shapes. Served hot with a side of awesomeness. - -#Building the library +#Building the KineticJS library To build the library, you need to have Ruby and Rubygems installed. After that, install the dependencies by running `bundle install`. To build a development version of the library, run `thor build:dev VERSION`, where VERSION is a string that can be anything you like. For example, using `thor build:dev core` will produce `kinetic-core.js`. To build a minified version of the library, run `thor build:prod VERSION`. If you want to add a release date other than the current day, use `-d="DATE"` (e.g. `-d="Mar 07 2012`). diff --git a/dist/kinetic-core.js b/dist/kinetic-core.js index d26f9912..cb2a8fbe 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: Mar 12 2012 + * Date: Mar 13 2012 * * Copyright (C) 2011 - 2012 by Eric Rowell * @@ -74,8 +74,18 @@ Kinetic.GlobalObject = { var config = this.config; for(var key in config) { if(config.hasOwnProperty(key)) { - this.node[key] = config[key]; - this.node.getLayer().draw(); + if(config[key].x !== undefined || config[key].y !== undefined) { + var propArray = ["x", "y"]; + for(var n = 0; n < propArray.length; n++) { + var prop = propArray[n]; + if(config[key][prop] !== undefined) { + this.node[key][prop] = config[key][prop]; + } + } + } + else { + this.node[key] = config[key]; + } } } }, @@ -83,8 +93,18 @@ Kinetic.GlobalObject = { var config = this.config; for(var key in config) { if(config.hasOwnProperty(key)) { - this.node[key] += this.changes[key] * frame.timeDiff; - this.node.getLayer().draw(); + if(config[key].x !== undefined || config[key].y !== undefined) { + var propArray = ["x", "y"]; + for(var n = 0; n < propArray.length; n++) { + var prop = propArray[n]; + if(config[key][prop] !== undefined) { + this.node[key][prop] += this.changes[key][prop] * frame.timeDiff; + } + } + } + else { + this.node[key] += this.changes[key] * frame.timeDiff; + } } } }, @@ -117,13 +137,17 @@ Kinetic.GlobalObject = { var didTransition = false; // loop through transitions for(var i = 0; i < layer.transitions.length; i++) { + didTransition = true; var transition = layer.transitions[i]; transition.time += this.frame.timeDiff; if(transition.time >= transition.config.duration * 1000) { this._endTransition.apply(transition); this._removeTransition(transition); - } else { - didTransition = true; + if(transition.config.callback !== undefined) { + transition.config.callback(); + } + } + else { this._linearTransition.apply(transition, [this.frame]); } } @@ -139,7 +163,8 @@ Kinetic.GlobalObject = { var time = date.getTime(); if(this.frame.lastTime === 0) { this.frame.lastTime = time; - } else { + } + else { this.frame.timeDiff = time - this.frame.lastTime; this.frame.lastTime = time; this.frame.time += this.frame.timeDiff; @@ -160,7 +185,9 @@ Kinetic.GlobalObject = { if(!this.isAnimating && this._isaCanvasAnimating()) { this.isAnimating = true; that._animationLoop(); - } else if(this.isAnimating && !this._isaCanvasAnimating()) { + } + else + if(this.isAnimating && !this._isaCanvasAnimating()) { this.isAnimating = false; this.frame.lastTime = 0; } @@ -172,7 +199,6 @@ window.requestAnimFrame = (function(callback) { function(callback) { window.setTimeout(callback, 1000 / 60); }; - })(); /////////////////////////////////////////////////////////////////////// @@ -309,7 +335,8 @@ Kinetic.Node.prototype = { break; } } - } else { + } + else { this.eventListeners[baseEvent] = undefined; } } @@ -342,7 +369,8 @@ Kinetic.Node.prototype = { if(scaleY) { this.scale.x = scaleX; this.scale.y = scaleY; - } else { + } + else { this.scale.x = scaleX; this.scale.y = scaleX; } @@ -535,7 +563,8 @@ Kinetic.Node.prototype = { if(needInit) { this._initDrag(); } - } else { + } + else { this.drag.x = false; this.drag.y = false; this._dragCleanup(); @@ -552,7 +581,8 @@ Kinetic.Node.prototype = { if(needInit) { this._initDrag(); } - } else { + } + else { this.drag.x = false; this._dragCleanup(); } @@ -568,7 +598,8 @@ Kinetic.Node.prototype = { if(needInit) { this._initDrag(); } - } else { + } + else { this.drag.y = false; this._dragCleanup(); } @@ -614,7 +645,8 @@ Kinetic.Node.prototype = { getLayer: function() { if(this.className === 'Layer') { return this; - } else { + } + else { return this.getParent().getLayer(); } }, @@ -624,7 +656,8 @@ Kinetic.Node.prototype = { getStage: function() { if(this.className === 'Stage') { return this; - } else { + } + else { return this.getParent().getStage(); } }, @@ -650,17 +683,32 @@ Kinetic.Node.prototype = { return this.centerOffset; }, /** - * transition node to another state + * transition node to another state. Any property that can accept a real + * number such as x, y, rotation, alpha, strokeWidth, radius, scale.x, scale.y, + * centerOffset.x and centerOffset.y can be transitioned * @param {Object} config */ transitionTo: function(config) { var layer = this.getLayer(); - var that = this; + var duration = config.duration * 1000; var changes = {}; + for(var key in config) { if(config.hasOwnProperty(key)) { - changes[key] = (config[key] - that[key]) / (config.duration * 1000); + if(config[key].x !== undefined || config[key].y !== undefined) { + changes[key] = {}; + var propArray = ["x", "y"]; + for(var n = 0; n < propArray.length; n++) { + var prop = propArray[n]; + if(config[key][prop] !== undefined) { + changes[key][prop] = (config[key][prop] - that[key][prop]) / duration; + } + } + } + else { + changes[key] = (config[key] - that[key]) / duration; + } } } @@ -718,7 +766,6 @@ Kinetic.Node.prototype = { handle(obj.parent); } } - /* * simulate bubbling by handling node events * first, followed by group events, followed @@ -1611,7 +1658,9 @@ Kinetic.Shape = function(config) { if(config.stroke !== undefined || config.strokeWidth !== undefined) { if(config.stroke === undefined) { config.stroke = "black"; - } else if(config.strokeWidth === undefined) { + } + else + if(config.strokeWidth === undefined) { config.strokeWidth = 2; } } @@ -1627,11 +1676,11 @@ Kinetic.Shape = function(config) { */ Kinetic.Shape.prototype = { /** - * get layer context where the shape is being drawn. When - * the shape is being rendered, .getContext() returns the context of the - * user created layer that contains the shape. When the event detection - * engine is determining whether or not an event has occured on that shape, - * .getContext() returns the context of the invisible backstage layer. + * get layer context where the shape is being drawn. When + * the shape is being rendered, .getContext() returns the context of the + * user created layer that contains the shape. When the event detection + * engine is determining whether or not an event has occured on that shape, + * .getContext() returns the context of the invisible backstage layer. */ getContext: function() { return this.tempLayer.getContext(); diff --git a/dist/kinetic-core.min.js b/dist/kinetic-core.min.js index 197827bc..43c07a89 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: Mar 12 2012 + * Date: Mar 13 2012 * * Copyright (C) 2011 - 2012 by Eric Rowell * @@ -25,4 +25,4 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -var Kinetic={};Kinetic.GlobalObject={stages:[],idCounter:0,isAnimating:!1,frame:{time:0,timeDiff:0,lastTime:0},drag:{moving:!1,node:undefined,offset:{x:0,y:0}},extend:function(a,b){for(var c in b.prototype)b.prototype.hasOwnProperty(c)&&a.prototype[c]===undefined&&(a.prototype[c]=b.prototype[c])},_isaCanvasAnimating:function(){for(var a=0;a=h.config.duration*1e3?(this._endTransition.apply(h),this._removeTransition(h)):(f=!0,this._linearTransition.apply(h,[this.frame]))}f&&e.draw()}}},_updateFrameObject:function(){var a=new Date,b=a.getTime();this.frame.lastTime===0?this.frame.lastTime=b:(this.frame.timeDiff=b-this.frame.lastTime,this.frame.lastTime=b,this.frame.time+=this.frame.timeDiff)},_animationLoop:function(){if(this.isAnimating){this._updateFrameObject(),this._runFrames();var a=this;requestAnimFrame(function(){a._animationLoop()})}},_handleAnimation:function(){var a=this;!this.isAnimating&&this._isaCanvasAnimating()?(this.isAnimating=!0,a._animationLoop()):this.isAnimating&&!this._isaCanvasAnimating()&&(this.isAnimating=!1,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.isListening=!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.drag={x:!1,y:!1};if(a)for(var b in a)switch(b){case"draggable":this.draggable(a[b]);break;case"draggableX":this.draggableX(a[b]);break;case"draggableY":this.draggableY(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.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&&(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.className!=="Stage")a*=b.alpha,b=b.parent;return a},draggable:function(a){if(a){var b=!this.drag.x&&!this.drag.y;this.drag.x=!0,this.drag.y=!0,b&&this._initDrag()}else this.drag.x=!1,this.drag.y=!1,this._dragCleanup()},draggableX:function(a){if(a){var b=!this.drag.x&&!this.drag.y;this.drag.x=!0,b&&this._initDrag()}else this.drag.x=!1,this._dragCleanup()},draggableY:function(a){if(a){var b=!this.drag.x&&!this.drag.y;this.drag.y=!0,b&&this._initDrag()}else this.drag.y=!1,this._dragCleanup()},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.className==="Layer"?this:this.getParent().getLayer()},getStage:function(){return this.className==="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.getLayer(),c=this,d={};for(var e in a)a.hasOwnProperty(e)&&(d[e]=(a[e]-c[e])/(a.duration*1e3));b.transitions.push({id:b.transitionIdCounter++,time:0,config:a,node:this,changes:d})},_initDrag:function(){var a=Kinetic.GlobalObject,b=this;this.on("mousedown.initdrag touchstart.initdrag",function(c){var d=b.getStage(),e=d.getUserPosition();e&&(a.drag.node=b,a.drag.offset.x=e.x-b.x,a.drag.offset.y=e.y-b.y)})},_dragCleanup:function(){!this.drag.x&&!this.drag.y&&(this.off("mousedown.initdrag"),this.off("touchstart.initdrag"))},_handleEvents:function(a,b){function c(d){var e=d.eventListeners;if(e[a]){var f=e[a];for(var g=0;g0)this.remove(this.children[0])},_remove:function(a){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.className==="Shape"){var f=this._detectEvent(e,b);if(f)return!0}else this._traverseChildren(e)}return!1},_handleEvent:function(a){var b=Kinetic.GlobalObject;a||(a=window.event),this._setMousePosition(a),this._setTouchPosition(a);var c=this.backstageLayer;c.clear(),this.targetFound=!1;for(var d=this.children.length-1;d>=0;d--){var e=this.children[d];e.visible&&d>=0&&e.isListening&&this._traverseChildren(e,a)&&(d=-1)}},_listen:function(){var a=this;this.container.addEventListener("mousedown",function(b){a.mouseDown=!0,a._handleEvent(b)},!1),this.container.addEventListener("mousemove",function(b){a.mouseUp=!1,a.mouseDown=!1,a._handleEvent(b)},!1),this.container.addEventListener("mouseup",function(b){a.mouseUp=!0,a.mouseDown=!1,a._handleEvent(b),a.clickStart=!1},!1),this.container.addEventListener("mouseover",function(b){a._handleEvent(b)},!1),this.container.addEventListener("mouseout",function(b){a.mousePos=undefined},!1),this.container.addEventListener("touchstart",function(b){b.preventDefault(),a.touchStart=!0,a._handleEvent(b)},!1),this.container.addEventListener("touchmove",function(b){b.preventDefault(),a._handleEvent(b)},!1),this.container.addEventListener("touchend",function(b){b.preventDefault(),a.touchEnd=!0,a._handleEvent(b)},!1)},_setMousePosition:function(a){var b=a.clientX-this._getContainerPosition().left+window.pageXOffset,c=a.clientY-this._getContainerPosition().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._getContainerPosition().left+window.pageXOffset,d=b.clientY-this._getContainerPosition().top+window.pageYOffset;this.touchPos={x:c,y:d}}},_getContainerPosition:function(){var a=this.container,b=0,c=0;while(a&&a.tagName!=="BODY")b+=a.offsetTop,c+=a.offsetLeft,a=a.offsetParent;return{top:b,left:c}},_stripLayer:function(a){a.context.stroke=function(){},a.context.fill=function(){},a.context.fillRect=function(b,c,d,e){a.context.rect(b,c,d,e)},a.context.strokeRect=function(b,c,d,e){a.context.rect(b,c,d,e)},a.context.drawImage=function(){},a.context.fillText=function(){},a.context.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.on("mousemove touchmove",function(b){var c=Kinetic.GlobalObject;if(c.drag.node){var d=a.getUserPosition();c.drag.node.drag.x&&(c.drag.node.x=d.x-c.drag.offset.x),c.drag.node.drag.y&&(c.drag.node.y=d.y-c.drag.offset.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.on("mouseup touchend mouseout",function(b){a._endDrag(b)})}},Kinetic.GlobalObject.extend(Kinetic.Stage,Kinetic.Container),Kinetic.Layer=function(a){this.className="Layer",this.canvas=document.createElement("canvas"),this.context=this.canvas.getContext("2d"),this.canvas.style.position="absolute",this.transitions=[],this.transitionIdCounter=0,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.className="Group",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.className="Shape";if(a.stroke!==undefined||a.strokeWidth!==undefined)a.stroke===undefined?a.stroke="black":a.strokeWidth===undefined&&(a.strokeWidth=2);this.drawFunc=a.drawFunc,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())},setFill:function(a){this.fill=a},getFill:function(){return this.fill},setStroke:function(a){this.stroke=a},getStroke:function(){return this.stroke},setStrokeWidth:function(a){this.strokeWidth=a},getStrokeWidth:function(){return this.strokeWidth},_draw:function(a){if(this.visible){var b=a.getStage(),c=a.getContext(),d=[];d.unshift(this);var e=this.parent;while(e.className!=="Stage")d.unshift(e),e=e.parent;for(var f=0;f=h.config.duration*1e3?(this._endTransition.apply(h),this._removeTransition(h),h.config.callback!==undefined&&h.config.callback()):this._linearTransition.apply(h,[this.frame])}f&&e.draw()}}},_updateFrameObject:function(){var a=new Date,b=a.getTime();this.frame.lastTime===0?this.frame.lastTime=b:(this.frame.timeDiff=b-this.frame.lastTime,this.frame.lastTime=b,this.frame.time+=this.frame.timeDiff)},_animationLoop:function(){if(this.isAnimating){this._updateFrameObject(),this._runFrames();var a=this;requestAnimFrame(function(){a._animationLoop()})}},_handleAnimation:function(){var a=this;!this.isAnimating&&this._isaCanvasAnimating()?(this.isAnimating=!0,a._animationLoop()):this.isAnimating&&!this._isaCanvasAnimating()&&(this.isAnimating=!1,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.isListening=!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.drag={x:!1,y:!1};if(a)for(var b in a)switch(b){case"draggable":this.draggable(a[b]);break;case"draggableX":this.draggableX(a[b]);break;case"draggableY":this.draggableY(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.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&&(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.className!=="Stage")a*=b.alpha,b=b.parent;return a},draggable:function(a){if(a){var b=!this.drag.x&&!this.drag.y;this.drag.x=!0,this.drag.y=!0,b&&this._initDrag()}else this.drag.x=!1,this.drag.y=!1,this._dragCleanup()},draggableX:function(a){if(a){var b=!this.drag.x&&!this.drag.y;this.drag.x=!0,b&&this._initDrag()}else this.drag.x=!1,this._dragCleanup()},draggableY:function(a){if(a){var b=!this.drag.x&&!this.drag.y;this.drag.y=!0,b&&this._initDrag()}else this.drag.y=!1,this._dragCleanup()},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.className==="Layer"?this:this.getParent().getLayer()},getStage:function(){return this.className==="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.getLayer(),c=this,d=a.duration*1e3,e={};for(var f in a)if(a.hasOwnProperty(f))if(a[f].x!==undefined||a[f].y!==undefined){e[f]={};var g=["x","y"];for(var h=0;h0)this.remove(this.children[0])},_remove:function(a){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.className==="Shape"){var f=this._detectEvent(e,b);if(f)return!0}else this._traverseChildren(e)}return!1},_handleEvent:function(a){var b=Kinetic.GlobalObject;a||(a=window.event),this._setMousePosition(a),this._setTouchPosition(a);var c=this.backstageLayer;c.clear(),this.targetFound=!1;for(var d=this.children.length-1;d>=0;d--){var e=this.children[d];e.visible&&d>=0&&e.isListening&&this._traverseChildren(e,a)&&(d=-1)}},_listen:function(){var a=this;this.container.addEventListener("mousedown",function(b){a.mouseDown=!0,a._handleEvent(b)},!1),this.container.addEventListener("mousemove",function(b){a.mouseUp=!1,a.mouseDown=!1,a._handleEvent(b)},!1),this.container.addEventListener("mouseup",function(b){a.mouseUp=!0,a.mouseDown=!1,a._handleEvent(b),a.clickStart=!1},!1),this.container.addEventListener("mouseover",function(b){a._handleEvent(b)},!1),this.container.addEventListener("mouseout",function(b){a.mousePos=undefined},!1),this.container.addEventListener("touchstart",function(b){b.preventDefault(),a.touchStart=!0,a._handleEvent(b)},!1),this.container.addEventListener("touchmove",function(b){b.preventDefault(),a._handleEvent(b)},!1),this.container.addEventListener("touchend",function(b){b.preventDefault(),a.touchEnd=!0,a._handleEvent(b)},!1)},_setMousePosition:function(a){var b=a.clientX-this._getContainerPosition().left+window.pageXOffset,c=a.clientY-this._getContainerPosition().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._getContainerPosition().left+window.pageXOffset,d=b.clientY-this._getContainerPosition().top+window.pageYOffset;this.touchPos={x:c,y:d}}},_getContainerPosition:function(){var a=this.container,b=0,c=0;while(a&&a.tagName!=="BODY")b+=a.offsetTop,c+=a.offsetLeft,a=a.offsetParent;return{top:b,left:c}},_stripLayer:function(a){a.context.stroke=function(){},a.context.fill=function(){},a.context.fillRect=function(b,c,d,e){a.context.rect(b,c,d,e)},a.context.strokeRect=function(b,c,d,e){a.context.rect(b,c,d,e)},a.context.drawImage=function(){},a.context.fillText=function(){},a.context.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.on("mousemove touchmove",function(b){var c=Kinetic.GlobalObject;if(c.drag.node){var d=a.getUserPosition();c.drag.node.drag.x&&(c.drag.node.x=d.x-c.drag.offset.x),c.drag.node.drag.y&&(c.drag.node.y=d.y-c.drag.offset.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.on("mouseup touchend mouseout",function(b){a._endDrag(b)})}},Kinetic.GlobalObject.extend(Kinetic.Stage,Kinetic.Container),Kinetic.Layer=function(a){this.className="Layer",this.canvas=document.createElement("canvas"),this.context=this.canvas.getContext("2d"),this.canvas.style.position="absolute",this.transitions=[],this.transitionIdCounter=0,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.className="Group",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.className="Shape";if(a.stroke!==undefined||a.strokeWidth!==undefined)a.stroke===undefined?a.stroke="black":a.strokeWidth===undefined&&(a.strokeWidth=2);this.drawFunc=a.drawFunc,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())},setFill:function(a){this.fill=a},getFill:function(){return this.fill},setStroke:function(a){this.stroke=a},getStroke:function(){return this.stroke},setStrokeWidth:function(a){this.strokeWidth=a},getStrokeWidth:function(){return this.strokeWidth},_draw:function(a){if(this.visible){var b=a.getStage(),c=a.getContext(),d=[];d.unshift(this);var e=this.parent;while(e.className!=="Stage")d.unshift(e),e=e.parent;for(var f=0;f= transition.config.duration * 1000) { this._endTransition.apply(transition); this._removeTransition(transition); - } else { - didTransition = true; + if(transition.config.callback !== undefined) { + transition.config.callback(); + } + } + else { this._linearTransition.apply(transition, [this.frame]); } } @@ -111,7 +135,8 @@ Kinetic.GlobalObject = { var time = date.getTime(); if(this.frame.lastTime === 0) { this.frame.lastTime = time; - } else { + } + else { this.frame.timeDiff = time - this.frame.lastTime; this.frame.lastTime = time; this.frame.time += this.frame.timeDiff; @@ -132,7 +157,9 @@ Kinetic.GlobalObject = { if(!this.isAnimating && this._isaCanvasAnimating()) { this.isAnimating = true; that._animationLoop(); - } else if(this.isAnimating && !this._isaCanvasAnimating()) { + } + else + if(this.isAnimating && !this._isaCanvasAnimating()) { this.isAnimating = false; this.frame.lastTime = 0; } @@ -144,5 +171,4 @@ window.requestAnimFrame = (function(callback) { function(callback) { window.setTimeout(callback, 1000 / 60); }; - })(); diff --git a/src/Node.js b/src/Node.js index 2e069063..b1b18149 100644 --- a/src/Node.js +++ b/src/Node.js @@ -132,7 +132,8 @@ Kinetic.Node.prototype = { break; } } - } else { + } + else { this.eventListeners[baseEvent] = undefined; } } @@ -165,7 +166,8 @@ Kinetic.Node.prototype = { if(scaleY) { this.scale.x = scaleX; this.scale.y = scaleY; - } else { + } + else { this.scale.x = scaleX; this.scale.y = scaleX; } @@ -358,7 +360,8 @@ Kinetic.Node.prototype = { if(needInit) { this._initDrag(); } - } else { + } + else { this.drag.x = false; this.drag.y = false; this._dragCleanup(); @@ -375,7 +378,8 @@ Kinetic.Node.prototype = { if(needInit) { this._initDrag(); } - } else { + } + else { this.drag.x = false; this._dragCleanup(); } @@ -391,7 +395,8 @@ Kinetic.Node.prototype = { if(needInit) { this._initDrag(); } - } else { + } + else { this.drag.y = false; this._dragCleanup(); } @@ -437,7 +442,8 @@ Kinetic.Node.prototype = { getLayer: function() { if(this.className === 'Layer') { return this; - } else { + } + else { return this.getParent().getLayer(); } }, @@ -447,7 +453,8 @@ Kinetic.Node.prototype = { getStage: function() { if(this.className === 'Stage') { return this; - } else { + } + else { return this.getParent().getStage(); } }, @@ -473,17 +480,32 @@ Kinetic.Node.prototype = { return this.centerOffset; }, /** - * transition node to another state + * transition node to another state. Any property that can accept a real + * number such as x, y, rotation, alpha, strokeWidth, radius, scale.x, scale.y, + * centerOffset.x and centerOffset.y can be transitioned * @param {Object} config */ transitionTo: function(config) { var layer = this.getLayer(); - var that = this; + var duration = config.duration * 1000; var changes = {}; + for(var key in config) { if(config.hasOwnProperty(key)) { - changes[key] = (config[key] - that[key]) / (config.duration * 1000); + if(config[key].x !== undefined || config[key].y !== undefined) { + changes[key] = {}; + var propArray = ["x", "y"]; + for(var n = 0; n < propArray.length; n++) { + var prop = propArray[n]; + if(config[key][prop] !== undefined) { + changes[key][prop] = (config[key][prop] - that[key][prop]) / duration; + } + } + } + else { + changes[key] = (config[key] - that[key]) / duration; + } } } @@ -541,7 +563,6 @@ Kinetic.Node.prototype = { handle(obj.parent); } } - /* * simulate bubbling by handling node events * first, followed by group events, followed diff --git a/src/Shape.js b/src/Shape.js index 0e741f91..2f891f3f 100644 --- a/src/Shape.js +++ b/src/Shape.js @@ -15,7 +15,9 @@ Kinetic.Shape = function(config) { if(config.stroke !== undefined || config.strokeWidth !== undefined) { if(config.stroke === undefined) { config.stroke = "black"; - } else if(config.strokeWidth === undefined) { + } + else + if(config.strokeWidth === undefined) { config.strokeWidth = 2; } } @@ -31,11 +33,11 @@ Kinetic.Shape = function(config) { */ Kinetic.Shape.prototype = { /** - * get layer context where the shape is being drawn. When - * the shape is being rendered, .getContext() returns the context of the - * user created layer that contains the shape. When the event detection - * engine is determining whether or not an event has occured on that shape, - * .getContext() returns the context of the invisible backstage layer. + * get layer context where the shape is being drawn. When + * the shape is being rendered, .getContext() returns the context of the + * user created layer that contains the shape. When the event detection + * engine is determining whether or not an event has occured on that shape, + * .getContext() returns the context of the invisible backstage layer. */ getContext: function() { return this.tempLayer.getContext(); diff --git a/tests/functionalTests.js b/tests/functionalTests.js index 385dae8c..50373120 100644 --- a/tests/functionalTests.js +++ b/tests/functionalTests.js @@ -2,11 +2,11 @@ function Test() { this.testOnly = ""; this.counter = 0; this.tests = { - "TRANSITION - transition position": function(containerId) { + "TRANSITION - transition position and rotation": function(containerId) { var stage = new Kinetic.Stage(containerId, 578, 200); var layer = new Kinetic.Layer(); var rect = new Kinetic.Rect({ - x: 10, + x: 100, y: 100, width: 100, height: 50,