diff --git a/dist/kinetic-core.js b/dist/kinetic-core.js index 98308b4e..130b7e4a 100644 --- a/dist/kinetic-core.js +++ b/dist/kinetic-core.js @@ -52,10 +52,6 @@ Kinetic.GlobalObject = { offset: { x: 0, y: 0 - }, - start: { - x: 0, - y: 0 } }, extend: function(obj1, obj2) { @@ -300,6 +296,14 @@ Kinetic.Node = function(config) { } } } + + // overrides + if(this.centerOffset.x === undefined) { + this.centerOffset.x = 0; + } + if(this.centerOffset.y === undefined) { + this.centerOffset.y = 0; + } }; /* * Node methods @@ -436,18 +440,7 @@ Kinetic.Node.prototype = { * get absolute position relative to stage */ getAbsolutePosition: function() { - var x = this.x; - var y = this.y; - var parent = this.getParent(); - while(parent.className !== 'Stage') { - x += parent.x; - y += parent.y; - parent = parent.parent; - } - return { - x: x, - y: y - }; + return this.getAbsoluteTransform().getTranslation(); }, /** * move node by an amount @@ -819,10 +812,8 @@ Kinetic.Node.prototype = { var m = that.getTransform().getTranslation(); var am = that.getAbsoluteTransform().getTranslation(); go.drag.node = that; - go.drag.offset.x = pos.x - that.x; - go.drag.offset.y = pos.y - that.y; - go.drag.start.x = m.x - am.x; - go.drag.start.y = m.y - am.y; + go.drag.offset.x = pos.x - that.getAbsoluteTransform().getTranslation().x; + go.drag.offset.y = pos.y - that.getAbsoluteTransform().getTranslation().y; } }); }, @@ -1581,21 +1572,43 @@ Kinetic.Stage.prototype = { var pos = that.getUserPosition(); var dc = node.dragConstraint; var db = node.dragBounds; - var m = node.getTransform().getTranslation(); - var am = node.getAbsoluteTransform().getTranslation(); - if(dc === 'none' || dc === 'horizontal') { - var newX = pos.x - go.drag.offset.x; - if((db.left === undefined || db.left < newX) && (db.right === undefined || db.right > newX)) { - node.x = newX + m.x - (am.x + go.drag.start.x); - } + // default + var newNodePos = { + x: pos.x - go.drag.offset.x, + y: pos.y - go.drag.offset.y + }; + + // bounds overrides + if(db.left !== undefined && newNodePos.x < db.left) { + newNodePos.x = db.left; } - if(dc === 'none' || dc === 'vertical') { - var newY = pos.y - go.drag.offset.y; - if((db.top === undefined || db.top < newY) && (db.bottom === undefined || db.bottom > newY)) { - node.y = newY + m.y - (am.y + go.drag.start.y); - } + else if(db.right !== undefined && newNodePos.x > db.right) { + newNodePos.x = db.right; } + else if(db.top !== undefined && newNodePos.y < db.top) { + newNodePos.y = db.top; + } + else if(db.bottom !== undefined && newNodePos.y > db.bottom) { + newNodePos.y = db.bottom; + } + + // constraint overrides + if(dc === 'horizontal') { + newNodePos.y = node.y; + } + else if(dc === 'vertical') { + newNodePos.x = node.x; + } + + // magic + var it = node.getAbsoluteTransform(); + it.invert(); + it.translate(newNodePos.x, newNodePos.y); + + node.x += it.getTranslation().x; + node.y += it.getTranslation().y; + go.drag.node.getLayer().draw(); if(!go.drag.moving) { @@ -2624,6 +2637,24 @@ Kinetic.Transform.prototype = { this.m[4] = dx; this.m[5] = dy; }, + /** + * Invert the matrix + */ + invert: function() { + var d = 1 / (this.m[0] * this.m[3] - this.m[1] * this.m[2]); + var m0 = this.m[3] * d; + var m1 = -this.m[1] * d; + var m2 = -this.m[2] * d; + var m3 = this.m[0] * d; + var m4 = d * (this.m[2] * this.m[5] - this.m[3] * this.m[4]); + var m5 = d * (this.m[1] * this.m[4] - this.m[0] * this.m[5]); + this.m[0] = m0; + this.m[1] = m1; + this.m[2] = m2; + this.m[3] = m3; + this.m[4] = m4; + this.m[5] = m5; + }, /** * return matrix */ diff --git a/dist/kinetic-core.min.js b/dist/kinetic-core.min.js index 6768d1ed..ea0f705f 100644 --- a/dist/kinetic-core.min.js +++ b/dist/kinetic-core.min.js @@ -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,frame:{time:0,timeDiff:0,lastTime:0},drag:{moving:!1,node:undefined,offset:{x:0,y:0},start:{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;a0)return!0}}return this.frame.lastTime=0,!1},_endTransition:function(){var a=this.config;for(var b in a)if(a.hasOwnProperty(b))if(a[b].x!==undefined||a[b].y!==undefined){var c=["x","y"];for(var d=0;d=h.config.duration*1e3?(this._endTransition.apply(h),this._clearTransition(h.node),h.config.callback!==undefined&&h.config.callback()):this._runTransition(h)}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._isaCanvasAnimating()){this._updateFrameObject(),this._runFrames();var a=this;requestAnimFrame(function(){a._animationLoop()})}},_handleAnimation:function(){var a=this;this._isaCanvasAnimating()&&a._animationLoop()}},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.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]}},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){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.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={};Kinetic.GlobalObject._clearTransition(this);for(var f in a)if(a.hasOwnProperty(f)&&f!=="duration"&&f!=="easing"&&f!=="callback")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.isListening)if(e.className==="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);var c=this.backstageLayer;c.clear(),this.targetFound=!1;var d=!1;for(var e=this.children.length-1;e>=0;e--){var f=this.children[e];f.visible&&e>=0&&f.isListening&&this._traverseChildren(f,a)&&(e=-1,d=!0)}!d&&this.mouseoutShape&&(this.mouseoutShape._handleEvents("onmouseout",a),this.mouseoutShape=undefined)},_listen:function(){var a=this;this.container.addEventListener("mousedown",function(b){a.mouseDown=!0,a._handleStageEvent(b)},!1),this.container.addEventListener("mousemove",function(b){a.mouseUp=!1,a.mouseDown=!1,a._handleStageEvent(b)},!1),this.container.addEventListener("mouseup",function(b){a.mouseUp=!0,a.mouseDown=!1,a._handleStageEvent(b),a.clickStart=!1},!1),this.container.addEventListener("mouseover",function(b){a._handleStageEvent(b)},!1),this.container.addEventListener("mouseout",function(b){a.mousePos=undefined},!1),this.container.addEventListener("touchstart",function(b){b.preventDefault(),a.touchStart=!0,a._handleStageEvent(b)},!1),this.container.addEventListener("touchmove",function(b){b.preventDefault(),a._handleStageEvent(b)},!1),this.container.addEventListener("touchend",function(b){b.preventDefault(),a.touchEnd=!0,a._handleStageEvent(b)},!1)},_setMousePosition:function(a){var b=a.offsetX||a.clientX-this._getContainerPosition().left+window.pageXOffset,c=a.offsetY||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-a.scrollTop,c+=a.offsetLeft-a.scrollLeft,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.onContainer("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=d.getTransform().getTranslation(),i=d.getAbsoluteTransform().getTranslation();if(f==="none"||f==="horizontal"){var j=e.x-c.drag.offset.x;(g.left===undefined||g.leftj)&&(d.x=j+h.x-(i.x+c.drag.start.x))}if(f==="none"||f==="vertical"){var k=e.y-c.drag.offset.y;(g.top===undefined||g.topk)&&(d.y=k+h.y-(i.y+c.drag.start.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.onContainer("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,this.backstageLayer=new Kinetic.Layer,this.bufferLayer.parent=this,this.backstageLayer.parent=this,this._stripLayer(this.backstageLayer),this.bufferLayer.getCanvas().style.display="none",this.backstageLayer.getCanvas().style.display="none",this.bufferLayer.canvas.width=this.width,this.bufferLayer.canvas.height=this.height,this.content.appendChild(this.bufferLayer.canvas),this.backstageLayer.canvas.width=this.width,this.backstageLayer.canvas.height=this.height,this.content.appendChild(this.backstageLayer.canvas)}},Kinetic.GlobalObject.extend(Kinetic.Stage,Kinetic.Container),Kinetic.GlobalObject.extend(Kinetic.Stage,Kinetic.Node),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=[],e=this.parent;d.unshift(this);while(e)d.unshift(e),e=e.parent;c.save();for(var f=0;f0)return!0}}return this.frame.lastTime=0,!1},_endTransition:function(){var a=this.config;for(var b in a)if(a.hasOwnProperty(b))if(a[b].x!==undefined||a[b].y!==undefined){var c=["x","y"];for(var d=0;d=h.config.duration*1e3?(this._endTransition.apply(h),this._clearTransition(h.node),h.config.callback!==undefined&&h.config.callback()):this._runTransition(h)}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._isaCanvasAnimating()){this._updateFrameObject(),this._runFrames();var a=this;requestAnimFrame(function(){a._animationLoop()})}},_handleAnimation:function(){var a=this;this._isaCanvasAnimating()&&a._animationLoop()}},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.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.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){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.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={};Kinetic.GlobalObject._clearTransition(this);for(var f in a)if(a.hasOwnProperty(f)&&f!=="duration"&&f!=="easing"&&f!=="callback")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.isListening)if(e.className==="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);var c=this.backstageLayer;c.clear(),this.targetFound=!1;var d=!1;for(var e=this.children.length-1;e>=0;e--){var f=this.children[e];f.visible&&e>=0&&f.isListening&&this._traverseChildren(f,a)&&(e=-1,d=!0)}!d&&this.mouseoutShape&&(this.mouseoutShape._handleEvents("onmouseout",a),this.mouseoutShape=undefined)},_listen:function(){var a=this;this.container.addEventListener("mousedown",function(b){a.mouseDown=!0,a._handleStageEvent(b)},!1),this.container.addEventListener("mousemove",function(b){a.mouseUp=!1,a.mouseDown=!1,a._handleStageEvent(b)},!1),this.container.addEventListener("mouseup",function(b){a.mouseUp=!0,a.mouseDown=!1,a._handleStageEvent(b),a.clickStart=!1},!1),this.container.addEventListener("mouseover",function(b){a._handleStageEvent(b)},!1),this.container.addEventListener("mouseout",function(b){a.mousePos=undefined},!1),this.container.addEventListener("touchstart",function(b){b.preventDefault(),a.touchStart=!0,a._handleStageEvent(b)},!1),this.container.addEventListener("touchmove",function(b){b.preventDefault(),a._handleStageEvent(b)},!1),this.container.addEventListener("touchend",function(b){b.preventDefault(),a.touchEnd=!0,a._handleStageEvent(b)},!1)},_setMousePosition:function(a){var b=a.offsetX||a.clientX-this._getContainerPosition().left+window.pageXOffset,c=a.offsetY||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-a.scrollTop,c+=a.offsetLeft-a.scrollLeft,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.onContainer("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),f==="horizontal"?h.y=d.y:f==="vertical"&&(h.x=d.x);var i=d.getAbsoluteTransform();i.invert(),i.translate(h.x,h.y),d.x+=i.getTranslation().x,d.y+=i.getTranslation().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.onContainer("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,this.backstageLayer=new Kinetic.Layer,this.bufferLayer.parent=this,this.backstageLayer.parent=this,this._stripLayer(this.backstageLayer),this.bufferLayer.getCanvas().style.display="none",this.backstageLayer.getCanvas().style.display="none",this.bufferLayer.canvas.width=this.width,this.bufferLayer.canvas.height=this.height,this.content.appendChild(this.bufferLayer.canvas),this.backstageLayer.canvas.width=this.width,this.backstageLayer.canvas.height=this.height,this.content.appendChild(this.backstageLayer.canvas)}},Kinetic.GlobalObject.extend(Kinetic.Stage,Kinetic.Container),Kinetic.GlobalObject.extend(Kinetic.Stage,Kinetic.Node),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=[],e=this.parent;d.unshift(this);while(e)d.unshift(e),e=e.parent;c.save();for(var f=0;f newX)) { - node.x = newX + m.x - (am.x + go.drag.start.x); - } + // default + var newNodePos = { + x: pos.x - go.drag.offset.x, + y: pos.y - go.drag.offset.y + }; + + // bounds overrides + if(db.left !== undefined && newNodePos.x < db.left) { + newNodePos.x = db.left; } - if(dc === 'none' || dc === 'vertical') { - var newY = pos.y - go.drag.offset.y; - if((db.top === undefined || db.top < newY) && (db.bottom === undefined || db.bottom > newY)) { - node.y = newY + m.y - (am.y + go.drag.start.y); - } + else if(db.right !== undefined && newNodePos.x > db.right) { + newNodePos.x = db.right; } + else if(db.top !== undefined && newNodePos.y < db.top) { + newNodePos.y = db.top; + } + else if(db.bottom !== undefined && newNodePos.y > db.bottom) { + newNodePos.y = db.bottom; + } + + // constraint overrides + if(dc === 'horizontal') { + newNodePos.y = node.y; + } + else if(dc === 'vertical') { + newNodePos.x = node.x; + } + + // magic + var it = node.getAbsoluteTransform(); + it.invert(); + it.translate(newNodePos.x, newNodePos.y); + + node.x += it.getTranslation().x; + node.y += it.getTranslation().y; + go.drag.node.getLayer().draw(); if(!go.drag.moving) { diff --git a/src/Transform.js b/src/Transform.js index 27eef144..c3f65377 100644 --- a/src/Transform.js +++ b/src/Transform.js @@ -89,6 +89,24 @@ Kinetic.Transform.prototype = { this.m[4] = dx; this.m[5] = dy; }, + /** + * Invert the matrix + */ + invert: function() { + var d = 1 / (this.m[0] * this.m[3] - this.m[1] * this.m[2]); + var m0 = this.m[3] * d; + var m1 = -this.m[1] * d; + var m2 = -this.m[2] * d; + var m3 = this.m[0] * d; + var m4 = d * (this.m[2] * this.m[5] - this.m[3] * this.m[4]); + var m5 = d * (this.m[1] * this.m[4] - this.m[0] * this.m[5]); + this.m[0] = m0; + this.m[1] = m1; + this.m[2] = m2; + this.m[3] = m3; + this.m[4] = m4; + this.m[5] = m5; + }, /** * return matrix */ diff --git a/tests/js/functionalTests.js b/tests/js/functionalTests.js index f85e86b6..b4af5e06 100644 --- a/tests/js/functionalTests.js +++ b/tests/js/functionalTests.js @@ -988,7 +988,7 @@ Test.prototype.tests = { var layer = new Kinetic.Layer(); var rect = new Kinetic.Rect({ x: 200, - y: 80, + y: 20, width: 100, height: 50, fill: 'red', @@ -1325,14 +1325,14 @@ Test.prototype.tests = { var layer = new Kinetic.Layer(); var group = new Kinetic.Group({ scale: { - x: 1.5, - y: 1.5 + x: 2, + y: 2 } }); var circle = new Kinetic.Circle({ - x: stage.width / 2, - y: stage.height / 2, + x: 40, + y: 40, radius: 70, fill: 'red', stroke: 'black', diff --git a/tests/js/unitTests.js b/tests/js/unitTests.js index df9f4f0b..99b33adf 100644 --- a/tests/js/unitTests.js +++ b/tests/js/unitTests.js @@ -1031,7 +1031,7 @@ Test.prototype.tests = { layer.add(circle); layer.draw(); }, - 'SHAPES - move shape, group, and layer, and then get absolute position': function(containerId) { + 'TRANSFORMS - move shape, group, and layer, and then get absolute position': function(containerId) { var stage = new Kinetic.Stage({ container: containerId, width: 578, @@ -1069,6 +1069,44 @@ Test.prototype.tests = { layer.draw(); }, + 'TRANSFORMS - scale layer, rotate group, position shape, and then get absolute position': function(containerId) { + var stage = new Kinetic.Stage({ + container: containerId, + width: 578, + height: 200 + }); + var layer = new Kinetic.Layer({ + scale: { + x: 2, + y: 2 + } + }); + var group = new Kinetic.Group({ + x: 100, + rotationDeg: 90 + }); + + var rect = new Kinetic.Rect({ + x: 50, + y: 10, + width: 100, + height: 50, + fill: 'green', + stroke: 'black', + strokeWidth: 4, + draggable: true + }); + + group.add(rect); + layer.add(group); + stage.add(layer); + + // test absolute positions + test(rect.getAbsolutePosition().x == 180, 'rect should be at x = 180'); + test(rect.getAbsolutePosition().y == 100, 'rect should be at y = 100'); + + layer.draw(); + }, 'SHAPES - hide circle': function(containerId) { var stage = new Kinetic.Stage({ container: containerId,