changed commands property to data per Jason's request. This provides a similar nomenclature to the SVG path data property

This commit is contained in:
Eric Rowell 2012-05-29 21:34:04 -07:00
parent 2bc0465186
commit 84e400e0f0
4 changed files with 429 additions and 276 deletions

265
dist/kinetic-core.js vendored
View File

@ -3,7 +3,7 @@
* http://www.kineticjs.com/ * http://www.kineticjs.com/
* Copyright 2012, Eric Rowell * Copyright 2012, Eric Rowell
* Licensed under the MIT or GPL Version 2 licenses. * Licensed under the MIT or GPL Version 2 licenses.
* Date: May 28 2012 * Date: May 29 2012
* *
* Copyright (C) 2011 - 2012 by Eric Rowell * Copyright (C) 2011 - 2012 by Eric Rowell
* *
@ -4081,19 +4081,20 @@ Kinetic.GlobalObject.extend(Kinetic.Line, Kinetic.Shape);
// SVG Path // SVG Path
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
/** /**
* Path constructor. This shape was inspired by jfollas's * Path constructor. This shape was inspired by Jason Follas's
* SVG Path plugin * SVG Path plugin. Jason also helped build the parser and the
* drawing function.
* @constructor * @constructor
* @augments Kinetic.Shape * @augments Kinetic.Shape
* @param {Object} config * @param {Object} config
*/ */
Kinetic.Path = function(config) { Kinetic.Path = function(config) {
this.shapeType = "Path"; this.shapeType = "Path";
this.commandsArray = []; this.dataArray = [];
config.drawFunc = function() { config.drawFunc = function() {
var context = this.getContext(); var context = this.getContext();
var ca = this.commandsArray; var ca = this.dataArray;
// context position // context position
context.beginPath(); context.beginPath();
for(var n = 0; n < ca.length; n++) { for(var n = 0; n < ca.length; n++) {
@ -4106,6 +4107,12 @@ Kinetic.Path = function(config) {
case 'M': case 'M':
context.moveTo(p[0], p[1]); context.moveTo(p[0], p[1]);
break; 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': case 'z':
context.closePath(); context.closePath();
break; break;
@ -4117,26 +4124,51 @@ Kinetic.Path = function(config) {
// call super constructor // call super constructor
Kinetic.Shape.apply(this, [config]); Kinetic.Shape.apply(this, [config]);
this.commandsArray = this.getCommandsArray(); this.dataArray = this.getDataArray();
}; };
/* /*
* Path methods * Path methods
*/ */
Kinetic.Path.prototype = { Kinetic.Path.prototype = {
/** /**
* get parsed commands array from the commands * get parsed data array from the data
* string. V, v, H, h, and l commands are converted to * string. V, v, H, h, and l data are converted to
* L commands for the purpose of high performance Path * L data for the purpose of high performance Path
* rendering * 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 // command string
var cs = this.attrs.commands; var cs = this.attrs.data;
// command chars // 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 // convert white spaces to commas
cs = cs.replace(new RegExp(' ', 'g'), ','); 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++) { for(var n = 0; n < cc.length; n++) {
cs = cs.replace(new RegExp(cc[n], 'g'), '|' + cc[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++) { for(var i = 0; i < p.length; i++) {
p[i] = parseFloat(p[i]); p[i] = parseFloat(p[i]);
} }
// convert l, H, h, V, and v to L
switch(c) { while(p.length > 0) {
case 'M': if(isNaN(p[0]))// case for a trailing comma before next command
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];
break; 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') { if(c === 'z' || c === 'Z')
c = 'L'; ca.push({
p[0] = cpx; command: 'z',
p[1] = cpy; points: []
} });
ca.push({
command: c,
points: p
});
} }
return ca; return ca;
}, },
/** /**
* get SVG path commands string * get SVG path data string
*/ */
getCommands: function() { getData: function() {
return this.attrs.commands; return this.attrs.data;
}, },
/** /**
* set SVG path commands string. This method * set SVG path data string. This method
* also automatically parses the commands string * also automatically parses the data string
* into a commands array. Currently supported SVG commands: * into a data array. Currently supported SVG data:
* M, L, l, H, h, V, v, z * M, m, L, l, H, h, V, v, Q, q, T, t, C, c, S, s, Z, z
* @param {String} SVG path command string * @param {String} SVG path command string
*/ */
setCommands: function(commands) { setData: function(data) {
this.attrs.commands = commands; this.attrs.data = data;
this.commandsArray = this.getCommandsArray(); this.dataArray = this.getDataArray();
} }
}; };

File diff suppressed because one or more lines are too long

View File

@ -2,19 +2,20 @@
// SVG Path // SVG Path
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
/** /**
* Path constructor. This shape was inspired by jfollas's * Path constructor. This shape was inspired by Jason Follas's
* SVG Path plugin * SVG Path plugin. Jason also helped build the parser and the
* drawing function.
* @constructor * @constructor
* @augments Kinetic.Shape * @augments Kinetic.Shape
* @param {Object} config * @param {Object} config
*/ */
Kinetic.Path = function(config) { Kinetic.Path = function(config) {
this.shapeType = "Path"; this.shapeType = "Path";
this.commandsArray = []; this.dataArray = [];
config.drawFunc = function() { config.drawFunc = function() {
var context = this.getContext(); var context = this.getContext();
var ca = this.commandsArray; var ca = this.dataArray;
// context position // context position
context.beginPath(); context.beginPath();
for(var n = 0; n < ca.length; n++) { for(var n = 0; n < ca.length; n++) {
@ -27,12 +28,12 @@ Kinetic.Path = function(config) {
case 'M': case 'M':
context.moveTo(p[0], p[1]); context.moveTo(p[0], p[1]);
break; break;
case 'C': case 'C':
context.bezierCurveTo(p[0], p[1], p[2], p[3], p[4], p[5]); context.bezierCurveTo(p[0], p[1], p[2], p[3], p[4], p[5]);
break; break;
case 'Q': case 'Q':
context.quadraticCurveTo(p[0], p[1], p[2], p[3]); context.quadraticCurveTo(p[0], p[1], p[2], p[3]);
break; break;
case 'z': case 'z':
context.closePath(); context.closePath();
break; break;
@ -44,52 +45,51 @@ Kinetic.Path = function(config) {
// call super constructor // call super constructor
Kinetic.Shape.apply(this, [config]); Kinetic.Shape.apply(this, [config]);
this.commandsArray = this.getCommandsArray(); this.dataArray = this.getDataArray();
}; };
/* /*
* Path methods * Path methods
*/ */
Kinetic.Path.prototype = { Kinetic.Path.prototype = {
/** /**
* get parsed commands array from the commands * get parsed data array from the data
* string. V, v, H, h, and l commands are converted to * string. V, v, H, h, and l data are converted to
* L commands for the purpose of high performance Path * L data for the purpose of high performance Path
* rendering * 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
// 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 // command string
var cs = this.attrs.commands; var cs = this.attrs.data;
// command chars // command chars
var cc = ['m', 'M', 'l', 'L', 'v', 'V', 'h', 'H', 'z', 'Z', 'c', 'C', 'q', 'Q', 't', 'T', 's', 'S']; 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 // convert white spaces to commas
cs = cs.replace(new RegExp(' ', 'g'), ','); 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++) { for(var n = 0; n < cc.length; n++) {
cs = cs.replace(new RegExp(cc[n], 'g'), '|' + cc[n]); cs = cs.replace(new RegExp(cc[n], 'g'), '|' + cc[n]);
} }
@ -115,175 +115,179 @@ Kinetic.Path.prototype = {
for(var i = 0; i < p.length; i++) { for(var i = 0; i < p.length; i++) {
p[i] = parseFloat(p[i]); p[i] = parseFloat(p[i]);
} }
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': while(p.length > 0) {
cpx += p.shift(); if(isNaN(p[0]))// case for a trailing comma before next command
cmd = 'L'; break;
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({ var cmd = undefined;
command: cmd || c, var points = [];
points: 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; return ca;
}, },
/** /**
* get SVG path commands string * get SVG path data string
*/ */
getCommands: function() { getData: function() {
return this.attrs.commands; return this.attrs.data;
}, },
/** /**
* set SVG path commands string. This method * set SVG path data string. This method
* also automatically parses the commands string * also automatically parses the data string
* into a commands array. Currently supported SVG commands: * 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 * M, m, L, l, H, h, V, v, Q, q, T, t, C, c, S, s, Z, z
* @param {String} SVG path command string * @param {String} SVG path command string
*/ */
setCommands: function(commands) { setData: function(data) {
this.attrs.commands = commands; this.attrs.data = data;
this.commandsArray = this.getCommandsArray(); this.dataArray = this.getDataArray();
} }
}; };

View File

@ -1189,7 +1189,7 @@ Test.prototype.tests = {
var layer = new Kinetic.Layer(); var layer = new Kinetic.Layer();
var path = new Kinetic.Path({ var path = new Kinetic.Path({
commands: 'M200,100h100v50z', data: 'M200,100h100v50z',
fill: '#ccc', fill: '#ccc',
stroke: '#333', stroke: '#333',
strokeWidth: 2, strokeWidth: 2,
@ -1216,15 +1216,15 @@ Test.prototype.tests = {
stage.add(layer); stage.add(layer);
test(path.getCommands() === 'M200,100h100v50z', 'commands are incorrect'); test(path.getData() === 'M200,100h100v50z', 'data are incorrect');
test(path.getCommandsArray().length === 4, 'commands array should have 4 elements'); 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.getData() === 'M200', 'data are incorrect');
test(path.getCommandsArray().length === 1, 'commands array should have 1 element'); 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) { 'SHAPE - moveTo with implied lineTos and trailing comma': function(containerId) {
@ -1239,7 +1239,7 @@ Test.prototype.tests = {
var layer = new Kinetic.Layer(); var layer = new Kinetic.Layer();
var path = new Kinetic.Path({ var path = new Kinetic.Path({
commands: 'm200,100,100,0,0,50,z', data: 'm200,100,100,0,0,50,z',
fill: '#fcc', fill: '#fcc',
stroke: '#333', stroke: '#333',
strokeWidth: 2, strokeWidth: 2,
@ -1266,10 +1266,10 @@ Test.prototype.tests = {
stage.add(layer); stage.add(layer);
test(path.getCommands() === 'm200,100,100,0,0,50,z', 'commands are incorrect'); test(path.getData() === 'm200,100,100,0,0,50,z', 'data are incorrect');
test(path.getCommandsArray().length === 4, 'commands array should have 4 elements'); 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) { 'SHAPE - add map path': function(containerId) {
var stage = new Kinetic.Stage({ var stage = new Kinetic.Stage({
@ -1287,14 +1287,14 @@ Test.prototype.tests = {
var c = worldMap.shapes[key]; var c = worldMap.shapes[key];
var path = new Kinetic.Path({ var path = new Kinetic.Path({
commands: c, data: c,
fill: '#ccc', fill: '#ccc',
stroke: '#999', stroke: '#999',
strokeWidth: 1, strokeWidth: 1,
}); });
if (key === 'US') 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() { path.on('mouseover', function() {
this.setFill('red'); 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 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({ var path = new Kinetic.Path({
commands: c, data: c,
fill: '#ccc', fill: '#ccc',
stroke: '#999', stroke: '#999',
strokeWidth: 1, strokeWidth: 1,
@ -1362,7 +1362,7 @@ Test.prototype.tests = {
var c = "M200,300 Q400,50 600,300 T1000,300"; var c = "M200,300 Q400,50 600,300 T1000,300";
var path = new Kinetic.Path({ var path = new Kinetic.Path({
commands: c, data: c,
stroke: 'red', stroke: 'red',
strokeWidth: 5, strokeWidth: 5,
}); });
@ -1405,7 +1405,7 @@ Test.prototype.tests = {
})); }));
layer.add(new Kinetic.Path({ layer.add(new Kinetic.Path({
commands: "M200,300 L400,50L600,300L800,550L1000,300", data: "M200,300 L400,50L600,300L800,550L1000,300",
stroke: "#888", stroke: "#888",
strokeWidth: 2 strokeWidth: 2
})); }));
@ -1428,7 +1428,7 @@ Test.prototype.tests = {
var c = "M100,200 C100,100 250,100 250,200 S400,300 400,200"; var c = "M100,200 C100,100 250,100 250,200 S400,300 400,200";
var path = new Kinetic.Path({ var path = new Kinetic.Path({
commands: c, data: c,
stroke: 'red', stroke: 'red',
strokeWidth: 5, strokeWidth: 5,
}); });