diff --git a/src/shapes/Path.js b/src/shapes/Path.js index 255dc9ca..66c984f0 100644 --- a/src/shapes/Path.js +++ b/src/shapes/Path.js @@ -35,21 +35,21 @@ Kinetic.Path = function(config) { context.quadraticCurveTo(p[0], p[1], p[2], p[3]); break; case 'A': - var cx = p[0], cy = p[1], rx = p[2], ry = p[3], theta = p[4], dTheta = p[5], psi = p[6], fs = p[7]; - - var r = (rx > ry) ? rx : ry; - var scaleX = (rx > ry) ? 1 : rx / ry; - var scaleY = (rx > ry) ? ry / rx : 1; + var cx = p[0], cy = p[1], rx = p[2], ry = p[3], theta = p[4], dTheta = p[5], psi = p[6], fs = p[7]; + + var r = (rx > ry) ? rx : ry; + var scaleX = (rx > ry) ? 1 : rx / ry; + var scaleY = (rx > ry) ? ry / rx : 1; - context.translate(cx, cy); - context.rotate(psi); - context.scale(scaleX, scaleY); - context.arc(0, 0, r, theta, theta + dTheta, 1 - fs); - context.scale(1 / scaleX, 1 / scaleY); - context.rotate(-psi); - context.translate(-cx, -cy); - - break; + context.translate(cx, cy); + context.rotate(psi); + context.scale(scaleX, scaleY); + context.arc(0, 0, r, theta, theta + dTheta, 1 - fs); + context.scale(1 / scaleX, 1 / scaleY); + context.rotate(-psi); + context.translate(-cx, -cy); + + break; case 'z': context.closePath(); break; @@ -90,11 +90,11 @@ Kinetic.Path.prototype = { //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 - //a (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+ Relative Elliptical Arc + //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 + //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 @@ -320,48 +320,48 @@ Kinetic.Path.prototype = { }, _convertEndpointToCenterParameterization: function(x1, y1, x2, y2, fa, fs, rx, ry, psiDeg) { - // Derived from: http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes - - var psi = psiDeg * (Math.PI / 180.0); + // Derived from: http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes + + var psi = psiDeg * (Math.PI / 180.0); - var xp = Math.cos(psi) * (x1 - x2) / 2.0 + Math.sin(psi) * (y1 - y2) / 2.0; - var yp = -1 * Math.sin(psi) * (x1 - x2) / 2.0 + Math.cos(psi) * (y1 - y2) / 2.0; + var xp = Math.cos(psi) * (x1 - x2) / 2.0 + Math.sin(psi) * (y1 - y2) / 2.0; + var yp = -1 * Math.sin(psi) * (x1 - x2) / 2.0 + Math.cos(psi) * (y1 - y2) / 2.0; - var lambda = (xp*xp) / (rx*rx) + (yp*yp) / (ry*ry); - - if (lambda > 1) { - rx *= Math.sqrt(lambda); - ry *= Math.sqrt(lambda); - } - - var f = Math.sqrt((((rx*rx) * (ry*ry)) - ((rx*rx) * (yp*yp)) - ((ry*ry) * (xp*xp))) / ((rx*rx) * (yp*yp) + (ry*ry) * (xp*xp))); - - if (fa == fs) f *= -1; - if (isNaN(f)) f = 0; - - var cxp = f * rx * yp / ry; - var cyp = f * -ry * xp / rx; - - var cx = (x1 + x2) / 2.0 + Math.cos(psi) * cxp - Math.sin(psi) * cyp; - var cy = (y1 + y2) / 2.0 + Math.sin(psi) * cxp + Math.cos(psi) * cyp; - - var vMag = function(v) { return Math.sqrt(v[0]*v[0] + v[1]*v[1]); } - var vRatio = function(u, v) { return (u[0]*v[0] + u[1]*v[1]) / (vMag(u) * vMag(v)) } - var vAngle = function(u, v) { return (u[0]*v[1] < u[1]*v[0] ? -1 : 1) * Math.acos(vRatio(u,v)); } - - var theta = vAngle([1,0], [(xp - cxp) / rx, (yp - cyp) / ry]); + var lambda = (xp*xp) / (rx*rx) + (yp*yp) / (ry*ry); + + if (lambda > 1) { + rx *= Math.sqrt(lambda); + ry *= Math.sqrt(lambda); + } + + var f = Math.sqrt((((rx*rx) * (ry*ry)) - ((rx*rx) * (yp*yp)) - ((ry*ry) * (xp*xp))) / ((rx*rx) * (yp*yp) + (ry*ry) * (xp*xp))); + + if (fa == fs) f *= -1; + if (isNaN(f)) f = 0; + + var cxp = f * rx * yp / ry; + var cyp = f * -ry * xp / rx; + + var cx = (x1 + x2) / 2.0 + Math.cos(psi) * cxp - Math.sin(psi) * cyp; + var cy = (y1 + y2) / 2.0 + Math.sin(psi) * cxp + Math.cos(psi) * cyp; + + var vMag = function(v) { return Math.sqrt(v[0]*v[0] + v[1]*v[1]); } + var vRatio = function(u, v) { return (u[0]*v[0] + u[1]*v[1]) / (vMag(u) * vMag(v)) } + var vAngle = function(u, v) { return (u[0]*v[1] < u[1]*v[0] ? -1 : 1) * Math.acos(vRatio(u,v)); } + + var theta = vAngle([1,0], [(xp - cxp) / rx, (yp - cyp) / ry]); - var u = [(xp - cxp) / rx, (yp - cyp) / ry]; - var v = [(-1 * xp - cxp) / rx, (-1 * yp - cyp) / ry]; - var dTheta = vAngle(u, v); - - if (vRatio(u,v) <= -1) dTheta = Math.PI; - if (vRatio(u,v) >= 1) dTheta = 0; + var u = [(xp - cxp) / rx, (yp - cyp) / ry]; + var v = [(-1 * xp - cxp) / rx, (-1 * yp - cyp) / ry]; + var dTheta = vAngle(u, v); + + if (vRatio(u,v) <= -1) dTheta = Math.PI; + if (vRatio(u,v) >= 1) dTheta = 0; - if (fs == 0 && dTheta > 0) dTheta = dTheta - 2 * Math.PI; - if (fs == 1 && dTheta < 0) dTheta = dTheta + 2 * Math.PI; - - return [cx, cy, rx, ry, theta, dTheta, psi, fs]; + if (fs == 0 && dTheta > 0) dTheta = dTheta - 2 * Math.PI; + if (fs == 1 && dTheta < 0) dTheta = dTheta + 2 * Math.PI; + + return [cx, cy, rx, ry, theta, dTheta, psi, fs]; } }; diff --git a/tests/js/Test.js b/tests/js/Test.js index 099f497c..2db4e230 100644 --- a/tests/js/Test.js +++ b/tests/js/Test.js @@ -17,7 +17,7 @@ function log(message) { */ function Test() { //this.testOnly = 'EVENTS - mousedown mouseup mouseover mouseout mousemove click dblclick / touchstart touchend touchmove tap dbltap'; - this.testOnly = 'DRAG AND DROP - drag and drop stage'; + //this.testOnly = 'DRAG AND DROP - drag and drop stage'; this.counter = 0; testCounter = document.createElement('div'); diff --git a/tests/js/unitTests.js b/tests/js/unitTests.js index 1b93fca1..2ed773f3 100644 --- a/tests/js/unitTests.js +++ b/tests/js/unitTests.js @@ -42,16 +42,16 @@ Test.prototype.tests = { stage.setSize(3); test(stage.getSize().width === 3 && stage.getSize().height === 3, 'stage size should be 3 x 3'); stage.setSize({ - width: 4, - height: 5 + width: 4, + height: 5 }); test(stage.getSize().width === 4 && stage.getSize().height === 5, 'stage size should be 4 x 5'); stage.setSize({ - width: 6 + width: 6 }); test(stage.getSize().width === 6 && stage.getSize().height === 5, 'stage size should be 6 x 5'); stage.setSize({ - height: 7 + height: 7 }); test(stage.getSize().width === 6 && stage.getSize().height === 7, 'stage size should be 6 x 7'); stage.setSize([8, 9]); @@ -1640,7 +1640,7 @@ Test.prototype.tests = { stage.add(layer); }, - 'SHAPE - arc': function(containerId) { + 'SHAPE - arc': function(containerId) { var stage = new Kinetic.Stage({ container: containerId, width: 1024, @@ -1652,30 +1652,30 @@ Test.prototype.tests = { }); var layer = new Kinetic.Layer(); - var c = "M100,350 l 50,-25 a25,25 -30 0,1 50,-25 l 50,-25 a25,50 -30 0,1 50,-25 l 50,-25 a25,75 -30 0,1 50,-25 l 50,-25 a25,100 -30 0,1 50,-25 l 50,-25"; + var c = "M100,350 l 50,-25 a25,25 -30 0,1 50,-25 l 50,-25 a25,50 -30 0,1 50,-25 l 50,-25 a25,75 -30 0,1 50,-25 l 50,-25 a25,100 -30 0,1 50,-25 l 50,-25"; - var path = new Kinetic.Path({ - data: c, - fill: 'none', - stroke: '#999', - strokeWidth: 1, - }); + var path = new Kinetic.Path({ + data: c, + fill: 'none', + stroke: '#999', + strokeWidth: 1, + }); - path.on('mouseover', function() { - this.setFill('red'); - layer.draw(); - }); + path.on('mouseover', function() { + this.setFill('red'); + layer.draw(); + }); - path.on('mouseout', function() { - this.setFill('none'); - layer.draw(); - }); + path.on('mouseout', function() { + this.setFill('none'); + layer.draw(); + }); - layer.add(path); + layer.add(path); stage.add(layer); - }, - 'SHAPE - Tiger (RAWR!)': function(containerId) { + }, + 'SHAPE - Tiger (RAWR!)': function(containerId) { var stage = new Kinetic.Stage({ container: containerId, width: 1024, @@ -1685,19 +1685,19 @@ Test.prototype.tests = { y: 50 }); var layer = new Kinetic.Layer(); - var group = new Kinetic.Group(); - - for (var i=0; i < tiger.length; i++) - { - var path = new Kinetic.Path(tiger[i]); - group.add(path); - } - - group.draggable(true); - layer.add(group); + var group = new Kinetic.Group(); + + for (var i=0; i < tiger.length; i++) + { + var path = new Kinetic.Path(tiger[i]); + group.add(path); + } + + group.draggable(true); + layer.add(group); stage.add(layer); - }, + }, 'SHAPE - add shape with custom attr pointing to self': function(containerId) { var stage = new Kinetic.Stage({ container: containerId,