From 84e400e0f041e07eb4764a9a74b65ba4a4c76b3f Mon Sep 17 00:00:00 2001 From: Eric Rowell Date: Tue, 29 May 2012 21:34:04 -0700 Subject: [PATCH] changed commands property to data per Jason's request. This provides a similar nomenclature to the SVG path data property --- dist/kinetic-core.js | 265 ++++++++++++++++++++------ dist/kinetic-core.min.js | 4 +- src/shapes/Path.js | 402 ++++++++++++++++++++------------------- tests/js/unitTests.js | 34 ++-- 4 files changed, 429 insertions(+), 276 deletions(-) diff --git a/dist/kinetic-core.js b/dist/kinetic-core.js index a8205e64..b6de7390 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: May 28 2012 + * Date: May 29 2012 * * Copyright (C) 2011 - 2012 by Eric Rowell * @@ -4081,19 +4081,20 @@ Kinetic.GlobalObject.extend(Kinetic.Line, Kinetic.Shape); // SVG Path /////////////////////////////////////////////////////////////////////// /** - * Path constructor. This shape was inspired by jfollas's - * SVG Path plugin + * Path constructor. This shape was inspired by Jason Follas's + * SVG Path plugin. Jason also helped build the parser and the + * drawing function. * @constructor * @augments Kinetic.Shape * @param {Object} config */ Kinetic.Path = function(config) { this.shapeType = "Path"; - this.commandsArray = []; + this.dataArray = []; config.drawFunc = function() { var context = this.getContext(); - var ca = this.commandsArray; + var ca = this.dataArray; // context position context.beginPath(); for(var n = 0; n < ca.length; n++) { @@ -4106,6 +4107,12 @@ Kinetic.Path = function(config) { case 'M': context.moveTo(p[0], p[1]); break; + case 'C': + context.bezierCurveTo(p[0], p[1], p[2], p[3], p[4], p[5]); + break; + case 'Q': + context.quadraticCurveTo(p[0], p[1], p[2], p[3]); + break; case 'z': context.closePath(); break; @@ -4117,26 +4124,51 @@ Kinetic.Path = function(config) { // call super constructor Kinetic.Shape.apply(this, [config]); - this.commandsArray = this.getCommandsArray(); + this.dataArray = this.getDataArray(); }; /* * Path methods */ Kinetic.Path.prototype = { /** - * get parsed commands array from the commands - * string. V, v, H, h, and l commands are converted to - * L commands for the purpose of high performance Path + * get parsed data array from the data + * string. V, v, H, h, and l data are converted to + * L data for the purpose of high performance Path * rendering */ - getCommandsArray: function() { + getDataArray: function() { + + // Path Data Segment must begin with a moveTo + //m (x y)+ Relative moveTo (subsequent points are treated as lineTo) + //M (x y)+ Absolute moveTo (subsequent points are treated as lineTo) + //l (x y)+ Relative lineTo + //L (x y)+ Absolute LineTo + //h (x)+ Relative horizontal lineTo + //H (x)+ Absolute horizontal lineTo + //v (y)+ Relative vertical lineTo + //V (y)+ Absolute vertical lineTo + //z (closepath) + //Z (closepath) + //c (x1 y1 x2 y2 x y)+ Relative Bezier curve + //C (x1 y1 x2 y2 x y)+ Absolute Bezier curve + //q (x1 y1 x y)+ Relative Quadratic Bezier + //Q (x1 y1 x y)+ Absolute Quadratic Bezier + //t (x y)+ Shorthand/Smooth Relative Quadratic Bezier + //T (x y)+ Shorthand/Smooth Absolute Quadratic Bezier + //s (x2 y2 x y)+ Shorthand/Smooth Relative Bezier curve + //S (x2 y2 x y)+ Shorthand/Smooth Absolute Bezier curve + + // Note: SVG a,A not implemented here + //a (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+ Relative Elliptical Arc + //A (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+ Absolute Elliptical Arc + // command string - var cs = this.attrs.commands; + var cs = this.attrs.data; // command chars - var cc = ['M', 'l', 'L', 'v', 'V', 'h', 'H', 'z']; + var cc = ['m', 'M', 'l', 'L', 'v', 'V', 'h', 'H', 'z', 'Z', 'c', 'C', 'q', 'Q', 't', 'T', 's', 'S']; // convert white spaces to commas cs = cs.replace(new RegExp(' ', 'g'), ','); - // create pipes so that we can split the commands + // create pipes so that we can split the data for(var n = 0; n < cc.length; n++) { cs = cs.replace(new RegExp(cc[n], 'g'), '|' + cc[n]); } @@ -4162,62 +4194,179 @@ Kinetic.Path.prototype = { for(var i = 0; i < p.length; i++) { p[i] = parseFloat(p[i]); } - // convert l, H, h, V, and v to L - switch(c) { - case 'M': - cpx = p[0]; - cpy = p[1]; - break; - case 'l': - cpx += p[0]; - cpy += p[1]; - break; - case 'L': - cpx = p[0]; - cpy = p[1]; - break; - case 'h': - cpx += p[0]; - break; - case 'H': - cpx = p[0]; - break; - case 'v': - cpy += p[0]; - break; - case 'V': - cpy = p[0]; + + while(p.length > 0) { + if(isNaN(p[0]))// case for a trailing comma before next command break; + + var cmd = undefined; + var points = []; + + // convert l, H, h, V, and v to L + switch(c) { + + // Note: Keep the lineTo's above the moveTo's in this switch + case 'l': + cpx += p.shift(); + cpy += p.shift(); + cmd = 'L'; + points.push(cpx, cpy); + break; + case 'L': + cpx = p.shift(); + cpy = p.shift(); + points.push(cpx, cpy); + break; + + // Note: lineTo handlers need to be above this point + case 'm': + cpx += p.shift(); + cpy += p.shift(); + cmd = 'M'; + points.push(cpx, cpy); + c = 'l'; + // subsequent points are treated as relative lineTo + break; + case 'M': + cpx = p.shift(); + cpy = p.shift(); + cmd = 'M'; + points.push(cpx, cpy); + c = 'L'; + // subsequent points are treated as absolute lineTo + break; + + case 'h': + cpx += p.shift(); + cmd = 'L'; + points.push(cpx, cpy); + break; + case 'H': + cpx = p.shift(); + cmd = 'L'; + points.push(cpx, cpy); + break; + case 'v': + cpy += p.shift(); + cmd = 'L'; + points.push(cpx, cpy); + break; + case 'V': + cpy = p.shift(); + cmd = 'L'; + points.push(cpx, cpy); + break; + case 'C': + points.push(p.shift(), p.shift(), p.shift(), p.shift()); + cpx = p.shift(); + cpy = p.shift(); + points.push(cpx, cpy); + break; + case 'c': + points.push(cpx + p.shift(), cpy + p.shift(), cpx + p.shift(), cpy + p.shift()); + cpx += p.shift(); + cpy += p.shift(); + cmd = 'C' + points.push(cpx, cpy); + break; + case 'S': + var ctlPtx = cpx, ctlPty = cpy; + var prevCmd = ca[ca.length - 1]; + if(prevCmd.command === 'C') { + ctlPtx = cpx + (cpx - prevCmd.points[2]); + ctlPty = cpy + (cpy - prevCmd.points[3]); + } + points.push(ctlPtx, ctlPty, p.shift(), p.shift()) + cpx = p.shift(); + cpy = p.shift(); + cmd = 'C'; + points.push(cpx, cpy); + break; + case 's': + var ctlPtx = cpx, ctlPty = cpy; + var prevCmd = ca[ca.length - 1]; + if(prevCmd.command === 'C') { + ctlPtx = cpx + (cpx - prevCmd.points[2]); + ctlPty = cpy + (cpy - prevCmd.points[3]); + } + points.push(ctlPtx, ctlPty, cpx + p.shift(), cpy + p.shift()) + cpx += p.shift(); + cpy += p.shift(); + cmd = 'C'; + points.push(cpx, cpy); + break; + case 'Q': + points.push(p.shift(), p.shift()); + cpx = p.shift(); + cpy = p.shift(); + points.push(cpx, cpy); + break; + case 'q': + points.push(cpx + p.shift(), cpy + p.shift()); + cpx += p.shift(); + cpy += p.shift(); + cmd = 'Q' + points.push(cpx, cpy); + break; + case 'T': + var ctlPtx = cpx, ctlPty = cpy; + var prevCmd = ca[ca.length - 1]; + if(prevCmd.command === 'Q') { + ctlPtx = cpx + (cpx - prevCmd.points[0]); + ctlPty = cpy + (cpy - prevCmd.points[1]); + } + cpx = p.shift(); + cpy = p.shift(); + cmd = 'Q'; + points.push(ctlPtx, ctlPty, cpx, cpy); + break; + case 't': + var ctlPtx = cpx, ctlPty = cpy; + var prevCmd = ca[ca.length - 1]; + if(prevCmd.command === 'Q') { + ctlPtx = cpx + (cpx - prevCmd.points[0]); + ctlPty = cpy + (cpy - prevCmd.points[1]); + } + cpx += p.shift(); + cpy += p.shift(); + cmd = 'Q'; + points.push(ctlPtx, ctlPty, cpx, cpy); + break; + + } + + ca.push({ + command: cmd || c, + points: points + }); + } - // reassign command - if(c == 'l' || c == 'V' || c == 'v' || c == 'H' || c == 'h') { - c = 'L'; - p[0] = cpx; - p[1] = cpy; - } - ca.push({ - command: c, - points: p - }); + + if(c === 'z' || c === 'Z') + ca.push({ + command: 'z', + points: [] + }); } + return ca; }, /** - * get SVG path commands string + * get SVG path data string */ - getCommands: function() { - return this.attrs.commands; + getData: function() { + return this.attrs.data; }, /** - * set SVG path commands string. This method - * also automatically parses the commands string - * into a commands array. Currently supported SVG commands: - * M, L, l, H, h, V, v, z + * set SVG path data string. This method + * also automatically parses the data string + * into a data array. Currently supported SVG data: + * M, m, L, l, H, h, V, v, Q, q, T, t, C, c, S, s, Z, z * @param {String} SVG path command string */ - setCommands: function(commands) { - this.attrs.commands = commands; - this.commandsArray = this.getCommandsArray(); + setData: function(data) { + this.attrs.data = data; + this.dataArray = this.getDataArray(); } }; diff --git a/dist/kinetic-core.min.js b/dist/kinetic-core.min.js index cc77f009..8456f80d 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: May 28 2012 + * Date: May 29 2012 * * Copyright (C) 2011 - 2012 by Eric Rowell * @@ -26,4 +26,4 @@ * THE SOFTWARE. */ var Kinetic={};Kinetic.GlobalObject={stages:[],idCounter:0,tempNodes:[],animations:[],animIdCounter:0,animRunning:!1,maxDragTimeInterval:20,frame:{time:0,timeDiff:0,lastTime:0},drag:{moving:!1,node:undefined,offset:{x:0,y:0},lastDrawTime: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])},_pullNodes:function(a){var b=this.tempNodes;for(var c=0;c0){this._updateFrameObject(),this._runFrames();var a=this;requestAnimFrame(function(){a._animationLoop()})}else this.animRunning=!1,this.frame.lastTime=0},_handleAnimation:function(){var a=this;this.animRunning?this.frame.lastTime=0:(this.animRunning=!0,a._animationLoop())},_isElement:function(a){return!!a&&a.nodeType==1},_isFunction:function(a){return!!(a&&a.constructor&&a.call&&a.apply)},_isArray:function(a){return a.length!==undefined},_isObject:function(a){return a===Object(a)},_isNumber:function(a){return Object.prototype.toString.call(a)=="[object Number]"},_hasMethods:function(a){var b=[];for(var c in a)this._isFunction(a[c])&&b.push(c);return b.length>0},_getXY:function(a){if(this._isNumber(a))return{x:a,y:a};if(this._isArray(a)){if(a.length===1){var b=a[0];if(this._isNumber(b))return{x:b,y:b};if(this._isArray(b))return{x:b[0],y:b[1]};if(this._isObject(b))return b}else if(a.length>=2)return{x:a[0],y:a[1]}}else if(this._isObject(a))return a;return{x:0,y:0}},_getSize:function(a){if(this._isNumber(a))return{width:a,height:a};if(this._isArray(a))if(a.length===1){var b=a[0];if(this._isNumber(b))return{width:b,height:b};if(this._isArray(b)){if(b.length>=4)return{width:b[2],height:b[3]};if(b.length>=2)return{width:b[0],height:b[1]}}else if(this._isObject(b))return b}else{if(a.length>=4)return{width:a[2],height:a[3]};if(a.length>=2)return{width:a[0],height:a[1]}}else if(this._isObject(a))return a;return{width:0,height:0}},_getPoints:function(a){if(a===undefined)return[];if(this._isObject(a[0]))return a;var b=[];for(var c=0;c1?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(){this.setAttrs({scale:arguments})},getScale:function(){return this.attrs.scale},setPosition:function(){var a=Kinetic.GlobalObject._getXY(arguments);this.setAttrs(a)},setX:function(a){this.attrs.x=a},setY:function(a){this.attrs.y=a},getX:function(){return this.attrs.x},getY:function(){return this.attrs.y},setDetectionType:function(a){this.attrs.detectionType=a},getDetectionType:function(){return this.attrs.detectionType},getPosition:function(){return{x:this.attrs.x,y:this.attrs.y}},getAbsolutePosition:function(){return this.getAbsoluteTransform().getTranslation()},setAbsolutePosition:function(){var a=Kinetic.GlobalObject._getXY(arguments),b=this.attrs.rotation,c={x:this.attrs.scale.x,y:this.attrs.scale.y},d={x:this.attrs.centerOffset.x,y:this.attrs.centerOffset.y};this.attrs.rotation=0,this.attrs.scale={x:1,y:1};var e=this.getAbsoluteTransform();e.invert(),e.translate(a.x,a.y),a={x:this.attrs.x+e.getTranslation().x,y:this.attrs.y+e.getTranslation().y},this.setPosition(a.x,a.y),this.rotate(b),this.attrs.scale={x:c.x,y:c.y}},move:function(a,b){this.attrs.x+=a,this.attrs.y+=b},setRotation:function(a){this.attrs.rotation=a},setRotationDeg:function(a){this.attrs.rotation=a*Math.PI/180},getRotation:function(){return this.attrs.rotation},getRotationDeg:function(){return this.attrs.rotation*180/Math.PI},rotate:function(a){this.attrs.rotation+=a},rotateDeg:function(a){this.attrs.rotation+=a*Math.PI/180},listen:function(a){this.attrs.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.attrs.alpha=a},getAlpha:function(){return this.attrs.alpha},getAbsoluteAlpha:function(){var a=1,b=this;while(b.nodeType!=="Stage")a*=b.attrs.alpha,b=b.parent;return a},draggable:function(a){this.attrs.draggable!==a&&(a?this._listenDrag():this._dragCleanup(),this.attrs.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()},getParent:function(){return this.parent},getLayer:function(){return this.nodeType==="Layer"?this:this.getParent().getLayer()},getStage:function(){return this.nodeType==="Stage"?this:this.getParent()===undefined?undefined:this.getParent().getStage()},getName:function(){return this.attrs.name},setCenterOffset:function(){this.setAttrs({centerOffset:arguments})},getCenterOffset:function(){return this.attrs.centerOffset},transitionTo:function(a){var b=Kinetic.GlobalObject;this.transAnim!==undefined&&(b._removeAnimation(this.transAnim),this.transAnim=undefined);var c=this.nodeType==="Stage"?this:this.getLayer(),d=this,e=new Kinetic.Transition(this,a),f={func:function(){e.onEnterFrame()},node:c};return this.transAnim=f,b._addAnimation(f),e.onFinished=function(){b._removeAnimation(f),d.transAnim=undefined,a.callback!==undefined&&a.callback(),f.node.draw()},e.start(),b._handleAnimation(),e},setDragConstraint:function(a){this.attrs.dragConstraint=a},getDragConstraint:function(){return this.attrs.dragConstraint},setDragBounds:function(a){this.attrs.dragBounds=a},getDragBounds:function(){return this.attrs.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])},add:function(a){a._id=Kinetic.GlobalObject.idCounter++,a.index=this.children.length,a.parent=this,this.children.push(a);var b=a.getStage();if(b===undefined){var c=Kinetic.GlobalObject;c.tempNodes.push(a)}else{b._addId(a),b._addName(a);var c=Kinetic.GlobalObject;c._pullNodes(b)}return this._add!==undefined&&this._add(a),this},remove:function(a){if(a.index!==undefined&&this.children[a.index]._id==a._id){var b=this.getStage();b!==undefined&&(b._removeId(a),b._removeName(a));var c=Kinetic.GlobalObject;for(var d=0;d=0;d--){var e=c[d];if(e.attrs.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=new Date,c=b.getTime();this.lastEventTime=c;var d=Kinetic.GlobalObject;a||(a=window.event),this._setMousePosition(a),this._setTouchPosition(a),this.pathLayer.clear(),this.targetFound=!1;var e=!1;for(var f=this.children.length-1;f>=0;f--){var g=this.children[f];g.attrs.visible&&f>=0&&g.attrs.listening&&this._traverseChildren(g,a)&&(f=-1,e=!0)}!e&&this.mouseoutShape&&(this.mouseoutShape._handleEvents("onmouseout",a),this.mouseoutShape=undefined)},_listen:function(){var a=Kinetic.GlobalObject,b=this;this.content.addEventListener("mousedown",function(a){b.mouseDown=!0,b.attrs.draggable&&b._initDrag(),b._handleStageEvent(a)},!1),this.content.addEventListener("mousemove",function(a){var c=b.attrs.throttle,d=new Date,e=d.getTime(),f=e-b.lastEventTime,g=1e3/c;f>=g&&(b.mouseUp=!1,b.mouseDown=!1,b._handleStageEvent(a))},!1),this.content.addEventListener("mouseup",function(a){b.mouseUp=!0,b.mouseDown=!1,b._handleStageEvent(a),b.clickStart=!1},!1),this.content.addEventListener("mouseover",function(a){b._handleStageEvent(a)},!1),this.content.addEventListener("mouseout",function(a){var c=b.targetShape;c&&(c._handleEvents("onmouseout",a),b.targetShape=undefined),b.mousePos=undefined},!1),this.content.addEventListener("touchstart",function(a){a.preventDefault(),b.touchStart=!0,b.attrs.draggable&&b._initDrag(),b._handleStageEvent(a)},!1),this.content.addEventListener("touchmove",function(a){var c=b.attrs.throttle,d=new Date,e=d.getTime(),f=e-b.lastEventTime,g=1e3/c;f>=g&&(a.preventDefault(),b._handleStageEvent(a))},!1),this.content.addEventListener("touchend",function(a){a.preventDefault(),b.touchEnd=!0,b._handleStageEvent(a)},!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.attrs.dragConstraint,g=d.attrs.dragBounds,h={x:d.attrs.x,y:d.attrs.y},i={x:e.x-c.drag.offset.x,y:e.y-c.drag.offset.y};g.left!==undefined&&i.xg.right&&(i.x=g.right),g.top!==undefined&&i.yg.bottom&&(i.y=g.bottom),d.setAbsolutePosition(i),f==="horizontal"?d.attrs.y=h.y:f==="vertical"&&(d.attrs.x=h.x),c.drag.node.nodeType==="Stage"?c.drag.node.draw():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.position="relative",this.content.style.display="inline-block",this.content.className="kineticjs-content",this.attrs.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.className="kineticjs-buffer-layer",this.content.appendChild(this.bufferLayer.canvas),this.pathLayer.canvas.className="kineticjs-path-layer",this.content.appendChild(this.pathLayer.canvas),this.setSize(this.attrs.width,this.attrs.height)},_addId:function(a){a.attrs.id!==undefined&&(this.ids[a.attrs.id]=a)},_removeId:function(a){a.attrs.id!==undefined&&(this.ids[a.attrs.id]=undefined)},_addName:function(a){var b=a.attrs.name;b!==undefined&&(this.names[b]===undefined&&(this.names[b]=[]),this.names[b].push(a))},_removeName:function(a){if(a.attrs.name!==undefined){var b=this.names[a.attrs.name];if(b!==undefined)for(var c=0;c=e)this._draw(),this.drawTimeout!==undefined&&(clearTimeout(this.drawTimeout),this.drawTimeout=undefined);else if(this.drawTimeout===undefined){var f=this;this.drawTimeout=setTimeout(function(){f.draw()},17)}},setThrottle:function(a){this.attrs.throttle=a},getThrottle:function(){return this.attrs.throttle},beforeDraw:function(a){this.beforeDrawFunc=a},afterDraw:function(a){this.afterDrawFunc=a},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},_draw:function(){var a=new Date,b=a.getTime();this.lastDrawTime=b,this.beforeDrawFunc!==undefined&&this.beforeDrawFunc.call(this),this.clear(),this.attrs.visible&&(this.attrs.drawFunc!==undefined&&this.attrs.drawFunc.call(this),this._drawChildren()),this.afterDrawFunc!==undefined&&this.afterDrawFunc.call(this)}},Kinetic.GlobalObject.extend(Kinetic.Layer,Kinetic.Container),Kinetic.GlobalObject.extend(Kinetic.Layer,Kinetic.Node),Kinetic.Group=function(a){this.nodeType="Group",Kinetic.Container.apply(this,[]),Kinetic.Node.apply(this,[a])},Kinetic.Group.prototype={draw:function(){this.attrs.visible&&this._drawChildren()}},Kinetic.GlobalObject.extend(Kinetic.Group,Kinetic.Container),Kinetic.GlobalObject.extend(Kinetic.Group,Kinetic.Node),Kinetic.Shape=function(a){this.setDefaultAttrs({fill:undefined,stroke:undefined,strokeWidth:undefined,lineJoin:undefined,detectionType:"path",shadow:{blur:10,alpha:1,offset:{x:0,y:0}}}),this.data=[],this.nodeType="Shape",this.appliedShadow=!1,Kinetic.Node.apply(this,[a])},Kinetic.Shape.prototype={getContext:function(){return this.tempLayer===undefined?null:this.tempLayer.getContext()},getCanvas:function(){return this.tempLayer.getCanvas()},stroke:function(){var a=!1,b=this.getContext();b.save();if(!!this.attrs.stroke||!!this.attrs.strokeWidth){this.appliedShadow||(a=this._applyShadow());var c=this.attrs.stroke?this.attrs.stroke:"black",d=this.attrs.strokeWidth?this.attrs.strokeWidth:2;b.lineWidth=d,b.strokeStyle=c,b.stroke()}b.restore(),a&&this.stroke()},fill:function(){var a=!1,b=this.getContext();b.save();var c=this.attrs.fill;if(!!c){this.appliedShadow||(a=this._applyShadow());var d=c.start,e=c.end,f=null;if(typeof c=="string")f=this.attrs.fill,b.fillStyle=f,b.fill();else if(c.image!==undefined){var g=c.repeat===undefined?"repeat":c.repeat;f=b.createPattern(c.image,g),b.save(),c.offset!==undefined&&b.translate(c.offset.x,c.offset.y),b.fillStyle=f,b.fill(),b.restore()}else if(d.radius===undefined&&e.radius===undefined){var b=this.getContext(),h=b.createLinearGradient(d.x,d.y,e.x,e.y),i=c.colorStops;for(var j=0;j0){var f=this.attrs.points[c-1].x,g=this.attrs.points[c-1].y;this._dashedLine(f,g,d,e,this.attrs.dashArray)}else a.lineTo(d,e)}!this.attrs.lineCap||(a.lineCap=this.attrs.lineCap),this.stroke()},Kinetic.Shape.apply(this,[a])},Kinetic.Line.prototype={setPoints:function(a){this.setAttrs({points:a})},getPoints:function(){return this.attrs.points},setLineCap:function(a){this.attrs.lineCap=a},getLineCap:function(){return this.attrs.lineCap},setDashArray:function(a){this.attrs.dashArray=a},getDashArray:function(){return this.attrs.dashArray},_dashedLine:function(a,b,c,d,e){var f=this.getContext(),g=e.length,h=c-a,i=d-b,j=h>i,k=j?i/h:h/i;k>9999?k=9999:k<-9999&&(k=-9999);var l=Math.sqrt(h*h+i*i),m=0,n=!0;while(l>=.1&&m<1e4){var o=e[m++%g];o===0&&(o=.001),o>l&&(o=l);var p=Math.sqrt(o*o/(1+k*k));j?(a+=h<0&&i<0?p*-1:p,b+=h<0&&i<0?k*p*-1:k*p):(a+=h<0&&i<0?k*p*-1:k*p,b+=h<0&&i<0?p*-1:p),f[n?"lineTo":"moveTo"](a,b),l-=o,n=!n}f.moveTo(c,d)}},Kinetic.GlobalObject.extend(Kinetic.Line,Kinetic.Shape),Kinetic.Path=function(a){this.shapeType="Path",this.commandsArray=[],a.drawFunc=function(){var a=this.getContext(),b=this.commandsArray;a.beginPath();for(var c=0;c0&&j[0]===""&&j.shift();for(var k=0;k=c.tweens.length&&c.onFinished()}}},Kinetic.Transition.prototype={add:function(a){this.tweens.push(a)},start:function(){for(var a=0;athis.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){var f=this.attrs.points[c-1].x,g=this.attrs.points[c-1].y;this._dashedLine(f,g,d,e,this.attrs.dashArray)}else a.lineTo(d,e)}!this.attrs.lineCap||(a.lineCap=this.attrs.lineCap),this.stroke()},Kinetic.Shape.apply(this,[a])},Kinetic.Line.prototype={setPoints:function(a){this.setAttrs({points:a})},getPoints:function(){return this.attrs.points},setLineCap:function(a){this.attrs.lineCap=a},getLineCap:function(){return this.attrs.lineCap},setDashArray:function(a){this.attrs.dashArray=a},getDashArray:function(){return this.attrs.dashArray},_dashedLine:function(a,b,c,d,e){var f=this.getContext(),g=e.length,h=c-a,i=d-b,j=h>i,k=j?i/h:h/i;k>9999?k=9999:k<-9999&&(k=-9999);var l=Math.sqrt(h*h+i*i),m=0,n=!0;while(l>=.1&&m<1e4){var o=e[m++%g];o===0&&(o=.001),o>l&&(o=l);var p=Math.sqrt(o*o/(1+k*k));j?(a+=h<0&&i<0?p*-1:p,b+=h<0&&i<0?k*p*-1:k*p):(a+=h<0&&i<0?k*p*-1:k*p,b+=h<0&&i<0?p*-1:p),f[n?"lineTo":"moveTo"](a,b),l-=o,n=!n}f.moveTo(c,d)}},Kinetic.GlobalObject.extend(Kinetic.Line,Kinetic.Shape),Kinetic.Path=function(a){this.shapeType="Path",this.dataArray=[],a.drawFunc=function(){var a=this.getContext(),b=this.dataArray;a.beginPath();for(var c=0;c0&&j[0]===""&&j.shift();for(var k=0;k0){if(isNaN(j[0]))break;var l=undefined,m=[];switch(i){case"l":f+=j.shift(),g+=j.shift(),l="L",m.push(f,g);break;case"L":f=j.shift(),g=j.shift(),m.push(f,g);break;case"m":f+=j.shift(),g+=j.shift(),l="M",m.push(f,g),i="l";break;case"M":f=j.shift(),g=j.shift(),l="M",m.push(f,g),i="L";break;case"h":f+=j.shift(),l="L",m.push(f,g);break;case"H":f=j.shift(),l="L",m.push(f,g);break;case"v":g+=j.shift(),l="L",m.push(f,g);break;case"V":g=j.shift(),l="L",m.push(f,g);break;case"C":m.push(j.shift(),j.shift(),j.shift(),j.shift()),f=j.shift(),g=j.shift(),m.push(f,g);break;case"c":m.push(f+j.shift(),g+j.shift(),f+j.shift(),g+j.shift()),f+=j.shift(),g+=j.shift(),l="C",m.push(f,g);break;case"S":var n=f,o=g,p=e[e.length-1];p.command==="C"&&(n=f+(f-p.points[2]),o=g+(g-p.points[3])),m.push(n,o,j.shift(),j.shift()),f=j.shift(),g=j.shift(),l="C",m.push(f,g);break;case"s":var n=f,o=g,p=e[e.length-1];p.command==="C"&&(n=f+(f-p.points[2]),o=g+(g-p.points[3])),m.push(n,o,f+j.shift(),g+j.shift()),f+=j.shift(),g+=j.shift(),l="C",m.push(f,g);break;case"Q":m.push(j.shift(),j.shift()),f=j.shift(),g=j.shift(),m.push(f,g);break;case"q":m.push(f+j.shift(),g+j.shift()),f+=j.shift(),g+=j.shift(),l="Q",m.push(f,g);break;case"T":var n=f,o=g,p=e[e.length-1];p.command==="Q"&&(n=f+(f-p.points[0]),o=g+(g-p.points[1])),f=j.shift(),g=j.shift(),l="Q",m.push(n,o,f,g);break;case"t":var n=f,o=g,p=e[e.length-1];p.command==="Q"&&(n=f+(f-p.points[0]),o=g+(g-p.points[1])),f+=j.shift(),g+=j.shift(),l="Q",m.push(n,o,f,g)}e.push({command:l||i,points:m})}(i==="z"||i==="Z")&&e.push({command:"z",points:[]})}return e},getData:function(){return this.attrs.data},setData:function(a){this.attrs.data=a,this.dataArray=this.getDataArray()}},Kinetic.GlobalObject.extend(Kinetic.Path,Kinetic.Shape),Kinetic.Transform=function(){this.m=[1,0,0,1,0,0]},Kinetic.Transform.prototype={translate:function(a,b){this.m[4]+=this.m[0]*a+this.m[2]*b,this.m[5]+=this.m[1]*a+this.m[3]*b},scale:function(a,b){this.m[0]*=a,this.m[1]*=a,this.m[2]*=b,this.m[3]*=b},rotate:function(a){var b=Math.cos(a),c=Math.sin(a),d=this.m[0]*b+this.m[2]*c,e=this.m[1]*b+this.m[3]*c,f=this.m[0]*-c+this.m[2]*b,g=this.m[1]*-c+this.m[3]*b;this.m[0]=d,this.m[1]=e,this.m[2]=f,this.m[3]=g},getTranslation:function(){return{x:this.m[4],y:this.m[5]}},multiply:function(a){var b=this.m[0]*a.m[0]+this.m[2]*a.m[1],c=this.m[1]*a.m[0]+this.m[3]*a.m[1],d=this.m[0]*a.m[2]+this.m[2]*a.m[3],e=this.m[1]*a.m[2]+this.m[3]*a.m[3],f=this.m[0]*a.m[4]+this.m[2]*a.m[5]+this.m[4],g=this.m[1]*a.m[4]+this.m[3]*a.m[5]+this.m[5];this.m[0]=b,this.m[1]=c,this.m[2]=d,this.m[3]=e,this.m[4]=f,this.m[5]=g},invert:function(){var a=1/(this.m[0]*this.m[3]-this.m[1]*this.m[2]),b=this.m[3]*a,c=-this.m[1]*a,d=-this.m[2]*a,e=this.m[0]*a,f=a*(this.m[2]*this.m[5]-this.m[3]*this.m[4]),g=a*(this.m[1]*this.m[4]-this.m[0]*this.m[5]);this.m[0]=b,this.m[1]=c,this.m[2]=d,this.m[3]=e,this.m[4]=f,this.m[5]=g},getMatrix:function(){return this.m}},Kinetic.Transition=function(a,b){function d(a,b){for(var e in a)e!=="duration"&&e!=="easing"&&e!=="callback"&&(Kinetic.GlobalObject._isObject(a[e])?d(a[e],b[e]):c.add(c._getTween(b,e,a[e])))}this.node=a,this.config=b,this.tweens=[];var c=this;d(b,a.attrs);var e=0,c=this;for(var f=0;f=c.tweens.length&&c.onFinished()}}},Kinetic.Transition.prototype={add:function(a){this.tweens.push(a)},start:function(){for(var a=0;athis.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 0) - { - if (isNaN(p[0])) // case for a trailing comma before next command - break; - - var cmd = undefined; - var points = []; - - // convert l, H, h, V, and v to L - switch(c) { - - // Note: Keep the lineTo's above the moveTo's in this switch - case 'l': - cpx += p.shift(); - cpy += p.shift(); - cmd = 'L'; - points.push(cpx, cpy); - break; - case 'L': - cpx = p.shift(); - cpy = p.shift(); - points.push(cpx, cpy); - break; - - // Note: lineTo handlers need to be above this point - case 'm': - cpx += p.shift(); - cpy += p.shift(); - cmd = 'M'; - points.push(cpx, cpy); - c = 'l'; // subsequent points are treated as relative lineTo - break; - case 'M': - cpx = p.shift(); - cpy = p.shift(); - cmd = 'M'; - points.push(cpx, cpy); - c = 'L'; // subsequent points are treated as absolute lineTo - break; - case 'h': - cpx += p.shift(); - cmd = 'L'; - points.push(cpx, cpy); - break; - case 'H': - cpx = p.shift(); - cmd = 'L'; - points.push(cpx, cpy); - break; - case 'v': - cpy += p.shift(); - cmd = 'L'; - points.push(cpx, cpy); - break; - case 'V': - cpy = p.shift(); - cmd = 'L'; - points.push(cpx, cpy); - break; - case 'C': - points.push(p.shift(), p.shift(), p.shift(), p.shift()); - cpx = p.shift(); - cpy = p.shift(); - points.push(cpx, cpy); - break; - case 'c': - points.push(cpx + p.shift(), cpy + p.shift(), cpx + p.shift(), cpy + p.shift()); - cpx += p.shift(); - cpy += p.shift(); - cmd = 'C' - points.push(cpx, cpy); - break; - case 'S': - var ctlPtx = cpx, ctlPty = cpy; - var prevCmd = ca[ca.length-1]; - if (prevCmd.command === 'C') { - ctlPtx = cpx + (cpx - prevCmd.points[2]); - ctlPty = cpy + (cpy - prevCmd.points[3]); - } - points.push(ctlPtx, ctlPty, p.shift(), p.shift()) - cpx = p.shift(); - cpy = p.shift(); - cmd = 'C'; - points.push(cpx, cpy); - break; - case 's': - var ctlPtx = cpx, ctlPty = cpy; - var prevCmd = ca[ca.length-1]; - if (prevCmd.command === 'C') { - ctlPtx = cpx + (cpx - prevCmd.points[2]); - ctlPty = cpy + (cpy - prevCmd.points[3]); - } - points.push(ctlPtx, ctlPty, cpx + p.shift(), cpy + p.shift()) - cpx += p.shift(); - cpy += p.shift(); - cmd = 'C'; - points.push(cpx, cpy); - break; - case 'Q': - points.push(p.shift(), p.shift()); - cpx = p.shift(); - cpy = p.shift(); - points.push(cpx, cpy); - break; - case 'q': - points.push(cpx + p.shift(), cpy + p.shift()); - cpx += p.shift(); - cpy += p.shift(); - cmd = 'Q' - points.push(cpx, cpy); - break; - case 'T': - var ctlPtx = cpx, ctlPty = cpy; - var prevCmd = ca[ca.length-1]; - if (prevCmd.command === 'Q') { - ctlPtx = cpx + (cpx - prevCmd.points[0]); - ctlPty = cpy + (cpy - prevCmd.points[1]); - } - cpx = p.shift(); - cpy = p.shift(); - cmd = 'Q'; - points.push(ctlPtx, ctlPty, cpx, cpy); - break; - case 't': - var ctlPtx = cpx, ctlPty = cpy; - var prevCmd = ca[ca.length-1]; - if (prevCmd.command === 'Q') { - ctlPtx = cpx + (cpx - prevCmd.points[0]); - ctlPty = cpy + (cpy - prevCmd.points[1]); - } - cpx += p.shift(); - cpy += p.shift(); - cmd = 'Q'; - points.push(ctlPtx, ctlPty, cpx, cpy); - break; - - } + while(p.length > 0) { + if(isNaN(p[0]))// case for a trailing comma before next command + break; - ca.push({ - command: cmd || c, - points: points - }); + var cmd = undefined; + var points = []; + + // convert l, H, h, V, and v to L + switch(c) { + + // Note: Keep the lineTo's above the moveTo's in this switch + case 'l': + cpx += p.shift(); + cpy += p.shift(); + cmd = 'L'; + points.push(cpx, cpy); + break; + case 'L': + cpx = p.shift(); + cpy = p.shift(); + points.push(cpx, cpy); + break; + + // Note: lineTo handlers need to be above this point + case 'm': + cpx += p.shift(); + cpy += p.shift(); + cmd = 'M'; + points.push(cpx, cpy); + c = 'l'; + // subsequent points are treated as relative lineTo + break; + case 'M': + cpx = p.shift(); + cpy = p.shift(); + cmd = 'M'; + points.push(cpx, cpy); + c = 'L'; + // subsequent points are treated as absolute lineTo + break; + + case 'h': + cpx += p.shift(); + cmd = 'L'; + points.push(cpx, cpy); + break; + case 'H': + cpx = p.shift(); + cmd = 'L'; + points.push(cpx, cpy); + break; + case 'v': + cpy += p.shift(); + cmd = 'L'; + points.push(cpx, cpy); + break; + case 'V': + cpy = p.shift(); + cmd = 'L'; + points.push(cpx, cpy); + break; + case 'C': + points.push(p.shift(), p.shift(), p.shift(), p.shift()); + cpx = p.shift(); + cpy = p.shift(); + points.push(cpx, cpy); + break; + case 'c': + points.push(cpx + p.shift(), cpy + p.shift(), cpx + p.shift(), cpy + p.shift()); + cpx += p.shift(); + cpy += p.shift(); + cmd = 'C' + points.push(cpx, cpy); + break; + case 'S': + var ctlPtx = cpx, ctlPty = cpy; + var prevCmd = ca[ca.length - 1]; + if(prevCmd.command === 'C') { + ctlPtx = cpx + (cpx - prevCmd.points[2]); + ctlPty = cpy + (cpy - prevCmd.points[3]); + } + points.push(ctlPtx, ctlPty, p.shift(), p.shift()) + cpx = p.shift(); + cpy = p.shift(); + cmd = 'C'; + points.push(cpx, cpy); + break; + case 's': + var ctlPtx = cpx, ctlPty = cpy; + var prevCmd = ca[ca.length - 1]; + if(prevCmd.command === 'C') { + ctlPtx = cpx + (cpx - prevCmd.points[2]); + ctlPty = cpy + (cpy - prevCmd.points[3]); + } + points.push(ctlPtx, ctlPty, cpx + p.shift(), cpy + p.shift()) + cpx += p.shift(); + cpy += p.shift(); + cmd = 'C'; + points.push(cpx, cpy); + break; + case 'Q': + points.push(p.shift(), p.shift()); + cpx = p.shift(); + cpy = p.shift(); + points.push(cpx, cpy); + break; + case 'q': + points.push(cpx + p.shift(), cpy + p.shift()); + cpx += p.shift(); + cpy += p.shift(); + cmd = 'Q' + points.push(cpx, cpy); + break; + case 'T': + var ctlPtx = cpx, ctlPty = cpy; + var prevCmd = ca[ca.length - 1]; + if(prevCmd.command === 'Q') { + ctlPtx = cpx + (cpx - prevCmd.points[0]); + ctlPty = cpy + (cpy - prevCmd.points[1]); + } + cpx = p.shift(); + cpy = p.shift(); + cmd = 'Q'; + points.push(ctlPtx, ctlPty, cpx, cpy); + break; + case 't': + var ctlPtx = cpx, ctlPty = cpy; + var prevCmd = ca[ca.length - 1]; + if(prevCmd.command === 'Q') { + ctlPtx = cpx + (cpx - prevCmd.points[0]); + ctlPty = cpy + (cpy - prevCmd.points[1]); + } + cpx += p.shift(); + cpy += p.shift(); + cmd = 'Q'; + points.push(ctlPtx, ctlPty, cpx, cpy); + break; + + } + + ca.push({ + command: cmd || c, + points: points + }); + + } + + if(c === 'z' || c === 'Z') + ca.push({ + command: 'z', + points: [] + }); + } - } - - if (c === 'z' || c === 'Z') - ca.push( {command: 'z', points: [] }); - } - return ca; }, /** - * get SVG path commands string + * get SVG path data string */ - getCommands: function() { - return this.attrs.commands; + getData: function() { + return this.attrs.data; }, /** - * set SVG path commands string. This method - * also automatically parses the commands string - * into a commands array. Currently supported SVG commands: + * set SVG path data string. This method + * also automatically parses the data string + * into a data array. Currently supported SVG data: * M, m, L, l, H, h, V, v, Q, q, T, t, C, c, S, s, Z, z * @param {String} SVG path command string */ - setCommands: function(commands) { - this.attrs.commands = commands; - this.commandsArray = this.getCommandsArray(); + setData: function(data) { + this.attrs.data = data; + this.dataArray = this.getDataArray(); } }; diff --git a/tests/js/unitTests.js b/tests/js/unitTests.js index bbaed682..26eb67ce 100644 --- a/tests/js/unitTests.js +++ b/tests/js/unitTests.js @@ -1189,7 +1189,7 @@ Test.prototype.tests = { var layer = new Kinetic.Layer(); var path = new Kinetic.Path({ - commands: 'M200,100h100v50z', + data: 'M200,100h100v50z', fill: '#ccc', stroke: '#333', strokeWidth: 2, @@ -1216,15 +1216,15 @@ Test.prototype.tests = { stage.add(layer); - test(path.getCommands() === 'M200,100h100v50z', 'commands are incorrect'); - test(path.getCommandsArray().length === 4, 'commands array should have 4 elements'); + test(path.getData() === 'M200,100h100v50z', 'data are incorrect'); + test(path.getDataArray().length === 4, 'data array should have 4 elements'); - path.setCommands('M200'); + path.setData('M200'); - test(path.getCommands() === 'M200', 'commands are incorrect'); - test(path.getCommandsArray().length === 1, 'commands array should have 1 element'); + test(path.getData() === 'M200', 'data are incorrect'); + test(path.getDataArray().length === 1, 'data array should have 1 element'); - path.setCommands('M200,100h100v50z'); + path.setData('M200,100h100v50z'); }, 'SHAPE - moveTo with implied lineTos and trailing comma': function(containerId) { @@ -1239,7 +1239,7 @@ Test.prototype.tests = { var layer = new Kinetic.Layer(); var path = new Kinetic.Path({ - commands: 'm200,100,100,0,0,50,z', + data: 'm200,100,100,0,0,50,z', fill: '#fcc', stroke: '#333', strokeWidth: 2, @@ -1266,10 +1266,10 @@ Test.prototype.tests = { stage.add(layer); - test(path.getCommands() === 'm200,100,100,0,0,50,z', 'commands are incorrect'); - test(path.getCommandsArray().length === 4, 'commands array should have 4 elements'); + test(path.getData() === 'm200,100,100,0,0,50,z', 'data are incorrect'); + test(path.getDataArray().length === 4, 'data array should have 4 elements'); - test(path.getCommandsArray()[1].command === 'L', 'second command should be an implied lineTo'); + test(path.getDataArray()[1].command === 'L', 'second command should be an implied lineTo'); }, 'SHAPE - add map path': function(containerId) { var stage = new Kinetic.Stage({ @@ -1287,14 +1287,14 @@ Test.prototype.tests = { var c = worldMap.shapes[key]; var path = new Kinetic.Path({ - commands: c, + data: c, fill: '#ccc', stroke: '#999', strokeWidth: 1, }); if (key === 'US') - test(path.getCommandsArray()[0].command === 'M', 'first command should be a moveTo'); + test(path.getDataArray()[0].command === 'M', 'first command should be a moveTo'); path.on('mouseover', function() { this.setFill('red'); @@ -1327,7 +1327,7 @@ Test.prototype.tests = { var c = "M12.582,9.551C3.251,16.237,0.921,29.021,7.08,38.564l-2.36,1.689l4.893,2.262l4.893,2.262l-0.568-5.36l-0.567-5.359l-2.365,1.694c-4.657-7.375-2.83-17.185,4.352-22.33c7.451-5.338,17.817-3.625,23.156,3.824c5.337,7.449,3.625,17.813-3.821,23.152l2.857,3.988c9.617-6.893,11.827-20.277,4.935-29.896C35.591,4.87,22.204,2.658,12.582,9.551z"; var path = new Kinetic.Path({ - commands: c, + data: c, fill: '#ccc', stroke: '#999', strokeWidth: 1, @@ -1362,7 +1362,7 @@ Test.prototype.tests = { var c = "M200,300 Q400,50 600,300 T1000,300"; var path = new Kinetic.Path({ - commands: c, + data: c, stroke: 'red', strokeWidth: 5, }); @@ -1405,7 +1405,7 @@ Test.prototype.tests = { })); layer.add(new Kinetic.Path({ - commands: "M200,300 L400,50L600,300L800,550L1000,300", + data: "M200,300 L400,50L600,300L800,550L1000,300", stroke: "#888", strokeWidth: 2 })); @@ -1428,7 +1428,7 @@ Test.prototype.tests = { var c = "M100,200 C100,100 250,100 250,200 S400,300 400,200"; var path = new Kinetic.Path({ - commands: c, + data: c, stroke: 'red', strokeWidth: 5, });