From 4b62ecea7c9461c755ae720d278cdedf29caf0a2 Mon Sep 17 00:00:00 2001 From: Eric Rowell Date: Sat, 30 Nov 2013 00:24:47 -0800 Subject: [PATCH] combined Line, Spline, Blob, and Polygon into a single shape for more flexibility. converted allPoints property into cacheable getTensionPoints method --- Gruntfile.js | 3 - src/shapes/Blob.js | 128 -------------------------- src/shapes/Line.js | 150 +++++++++++++++++++++++++------ src/shapes/Polygon.js | 62 ------------- src/shapes/Spline.js | 115 ------------------------ test/unit/Node-test.js | 5 +- test/unit/shapes/Blob-test.js | 19 ++-- test/unit/shapes/Line-test.js | 3 +- test/unit/shapes/Polygon-test.js | 7 +- test/unit/shapes/Spline-test.js | 26 +++--- 10 files changed, 154 insertions(+), 364 deletions(-) delete mode 100644 src/shapes/Blob.js delete mode 100644 src/shapes/Polygon.js delete mode 100644 src/shapes/Spline.js diff --git a/Gruntfile.js b/Gruntfile.js index 3e776080..ed147c23 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -22,11 +22,8 @@ module.exports = function(grunt) { 'src/shapes/Ellipse.js', 'src/shapes/Wedge.js', 'src/shapes/Image.js', - 'src/shapes/Polygon.js', 'src/shapes/Text.js', 'src/shapes/Line.js', - 'src/shapes/Spline.js', - 'src/shapes/Blob.js', 'src/shapes/Sprite.js', // plugins diff --git a/src/shapes/Blob.js b/src/shapes/Blob.js deleted file mode 100644 index 980be09c..00000000 --- a/src/shapes/Blob.js +++ /dev/null @@ -1,128 +0,0 @@ -(function() { - /** - * Blob constructor. Blobs are defined by an array of points and - * a tension - * @constructor - * @memberof Kinetic - * @augments Kinetic.Shape - * @param {Object} config - * @param {Array} config.points can be a flattened array of points, an array of point arrays, or an array of point objects. - * e.g. [0,1,2,3], [[0,1],[2,3]] and [{x:0,y:1},{x:2,y:3}] are equivalent - * @param {Number} [config.tension] default value is 1. Higher values will result in a more curvy line. A value of 0 will result in no interpolation. - * @@shapeParams - * @@nodeParams - * @example - * var blob = new Kinetic.Blob({
- * points: [73, 140, 340, 23, 500, 109, 300, 170],
- * tension: 0.8,
- * fill: 'red',
- * stroke: 'black'
- * strokeWidth: 5
- * }); - */ - Kinetic.Blob = function(config) { - this.___init(config); - }; - - Kinetic.Blob.prototype = { - ___init: function(config) { - var that = this; - // call super constructor - Kinetic.Shape.call(this, config); - this.className = 'Blob'; - - this.on('pointsChange.kinetic tensionChange.kinetic', function() { - that._setAllPoints(); - }); - - this._setAllPoints(); - }, - drawFunc: function(context) { - var points = this.getPoints(), - length = points.length, - tension = this.getTension(), - ap, len, n, point; - - context.beginPath(); - context.moveTo(points[0].x, points[0].y); - - // tension - if(tension !== 0 && length > 2) { - ap = this.allPoints; - len = ap.length; - n = 0; - - while(n < len-1) { - context.bezierCurveTo(ap[n].x, ap[n++].y, ap[n].x, ap[n++].y, ap[n].x, ap[n++].y); - } - } - // no tension - else { - for(n = 1; n < length; n++) { - point = points[n]; - context.lineTo(point.x, point.y); - } - } - - context.closePath(); - context.fillStrokeShape(this); - }, - _setAllPoints: function() { - var points = this.getPoints(), - length = points.length, - tension = this.getTension(), - util = Kinetic.Util, - firstControlPoints = util._getControlPoints(points[length - 1], points[0], points[1], tension), - lastControlPoints = util._getControlPoints(points[length - 2], points[length - 1], points[0], tension); - - this.allPoints = Kinetic.Util._expandPoints(this.getPoints(), this.getTension()); - - // prepend control point - this.allPoints.unshift(firstControlPoints[1]); - - // append cp, point, cp, cp, first point - this.allPoints.push(lastControlPoints[0]); - this.allPoints.push(points[length - 1]); - this.allPoints.push(lastControlPoints[1]); - this.allPoints.push(firstControlPoints[0]); - this.allPoints.push(points[0]); - } - }; - - Kinetic.Util.extend(Kinetic.Blob, Kinetic.Shape); - - Kinetic.Factory.addGetterSetter(Kinetic.Blob, 'tension', 1); - /** - * get tension - * @name getTension - * @method - * @memberof Kinetic.Blob.prototype - * @returns {Number} - */ - - /** - * set tension - * @name setTension - * @method - * @memberof Kinetic.Blob.prototype - * @param {Number} tension - */ - - Kinetic.Factory.addPointsGetterSetter(Kinetic.Blob, 'points'); - /** - * get points array - * @name getPoints - * @method - * @memberof Kinetic.Blob.prototype - * @returns {Array} - */ - - /** - * set points array - * @name setPoints - * @method - * @memberof Kinetic.Blob.prototype - * @param {Array} can be an array of point objects or an array - * of Numbers. e.g. [{x:1,y:2},{x:3,y:4}] or [1,2,3,4] - */ -})(); diff --git a/src/shapes/Line.js b/src/shapes/Line.js index f7f54e12..1822507d 100644 --- a/src/shapes/Line.js +++ b/src/shapes/Line.js @@ -1,34 +1,23 @@ (function() { /** - * Line constructor.  Lines are defined by an array of points + * Line constructor.  Lines are defined by an array of points and + * a tension * @constructor * @memberof Kinetic * @augments Kinetic.Shape * @param {Object} config * @param {Array} config.points can be a flattened array of points, an array of point arrays, or an array of point objects. * e.g. [0,1,2,3], [[0,1],[2,3]] and [{x:0,y:1},{x:2,y:3}] are equivalent + * @param {Number} [config.tension] default value is 1. Higher values will result in a more curvy line. A value of 0 will result in no interpolation. * @@shapeParams * @@nodeParams * @example - * // simple line - * var line = new Kinetic.Line({
- * x: 100,
- * y: 50,
- * points: [73, 70, 340, 23, 450, 60, 500, 20],
- * stroke: 'red'
- * });

- * - * // dashed line with shadow
* var line = new Kinetic.Line({
* x: 100,
* y: 50,
* points: [73, 70, 340, 23, 450, 60, 500, 20],
* stroke: 'red',
- * dashArray: [33, 10],
- * shadowColor: 'black',
- * shadowBlur: 10,
- * shadowOffset: 10,
- * shadowOpacity: 0.5
+ * tension: 1
* }); */ Kinetic.Line = function(config) { @@ -37,29 +26,142 @@ Kinetic.Line.prototype = { ___init: function(config) { + var that = this; // call super constructor Kinetic.Shape.call(this, config); this.className = 'Line'; + + this.on('pointsChange.kinetic tensionChange.kinetic closedChange.kinetic', function() { + this._clearCache('tensionPoints'); + }); }, drawFunc: function(context) { var points = this.getPoints(), length = points.length, - n, point; + tension = this.getTension(), + closed = this.getClosed(), + tp, len, n, point; context.beginPath(); context.moveTo(points[0].x, points[0].y); - for(n = 1; n < length; n++) { - point = points[n]; - context.lineTo(point.x, point.y); + // tension + if(tension !== 0 && length > 2) { + tp = this.getTensionPoints(); + len = tp.length; + n = closed ? 0 : 2; + + if (!closed) { + context.quadraticCurveTo(tp[0].x, tp[0].y, tp[1].x, tp[1].y); + } + + while(n < len - 1) { + context.bezierCurveTo(tp[n].x, tp[n++].y, tp[n].x, tp[n++].y, tp[n].x, tp[n++].y); + } + + if (!closed) { + context.quadraticCurveTo(tp[len - 1].x, tp[len - 1].y, points[length - 1].x, points[length - 1].y); + } + } + // no tension + else { + for(n = 1; n < length; n++) { + point = points[n]; + context.lineTo(point.x, point.y); + } } - context.strokeShape(this); + // closed e.g. polygons and blobs + if (closed) { + context.closePath(); + context.fillStrokeShape(this); + } + // open e.g. lines and splines + else { + context.strokeShape(this); + }; + }, + getTensionPoints: function() { + return this._getCache('tensionPoints', this._getTensionPoints); + }, + _getTensionPoints: function() { + if (this.getClosed()) { + return this._getTensionPointsClosed(); + } + else { + return Kinetic.Util._expandPoints(this.getPoints(), this.getTension()); + } + }, + _getTensionPointsClosed: function() { + var points = this.getPoints(), + length = points.length, + tension = this.getTension(), + util = Kinetic.Util, + firstControlPoints = util._getControlPoints(points[length - 1], points[0], points[1], tension), + lastControlPoints = util._getControlPoints(points[length - 2], points[length - 1], points[0], tension), + tensionPoints = Kinetic.Util._expandPoints(points, tension); + + // prepend control point + tensionPoints.unshift(firstControlPoints[1]); + + // append cp, point, cp, cp, first point + tensionPoints.push(lastControlPoints[0]); + tensionPoints.push(points[length - 1]); + tensionPoints.push(lastControlPoints[1]); + tensionPoints.push(firstControlPoints[0]); + tensionPoints.push(points[0]); + + return tensionPoints; } }; Kinetic.Util.extend(Kinetic.Line, Kinetic.Shape); + // add getters setters + Kinetic.Factory.addGetterSetter(Kinetic.Line, 'closed', false); + + /** + * get closed + * @name getClosed + * @method + * @memberof Kinetic.Line.prototype + * @returns {Boolean} + */ + + /** + * set closed + * @name setClosed + * @method + * @memberof Kinetic.Line.prototype + * @param {Boolean} closed + */ + + Kinetic.Factory.addGetterSetter(Kinetic.Line, 'tension', 0); + + /** + * get tension + * @name getTension + * @method + * @memberof Kinetic.Line.prototype + * @returns {Number} + */ + + /** + * set tension + * @name setTension + * @method + * @memberof Kinetic.Line.prototype + * @param {Number} tension + */ + Kinetic.Factory.addPointsGetterSetter(Kinetic.Line, 'points'); + /** + * get points array + * @name getPoints + * @method + * @memberof Kinetic.Line.prototype + * @returns {Array} + */ + /** * set points array * @name setPoints @@ -68,12 +170,4 @@ * @param {Array} can be an array of point objects or an array * of Numbers. e.g. [{x:1,y:2},{x:3,y:4}] or [1,2,3,4] */ - - /** - * get points array - * @name getPoints - * @method - * @memberof Kinetic.Line.prototype - * @returns {Array} - */ })(); diff --git a/src/shapes/Polygon.js b/src/shapes/Polygon.js deleted file mode 100644 index 8f77d033..00000000 --- a/src/shapes/Polygon.js +++ /dev/null @@ -1,62 +0,0 @@ -(function() { - /** - * Polygon constructor.  Polygons are defined by an array of points - * @constructor - * @memberof Kinetic - * @augments Kinetic.Shape - * @param {Object} config - * @param {Array} config.points can be a flattened array of points, an array of point arrays, or an array of point objects. - * e.g. [0,1,2,3], [[0,1],[2,3]] and [{x:0,y:1},{x:2,y:3}] are equivalent - * @@shapeParams - * @@nodeParams - * @example - * var polygon = new Kinetic.Polygon({
- * points: [73, 192, 73, 160, 340, 23, 500, 109, 499, 139, 342, 93],
- * fill: '#00D2FF',
- * stroke: 'black',
- * strokeWidth: 5
- * }); - */ - Kinetic.Polygon = function(config) { - this.___init(config); - }; - - Kinetic.Polygon.prototype = { - ___init: function(config) { - // call super constructor - Kinetic.Shape.call(this, config); - this.className = 'Polygon'; - }, - drawFunc: function(context) { - var points = this.getPoints(), - length = points.length; - - context.beginPath(); - context.moveTo(points[0].x, points[0].y); - for(var n = 1; n < length; n++) { - context.lineTo(points[n].x, points[n].y); - } - context.closePath(); - context.fillStrokeShape(this); - } - }; - Kinetic.Util.extend(Kinetic.Polygon, Kinetic.Shape); - - Kinetic.Factory.addPointsGetterSetter(Kinetic.Polygon, 'points'); - /** - * set points array - * @name setPoints - * @method - * @memberof Kinetic.Polygon.prototype - * @param {Array} can be an array of point objects or an array - * of Numbers. e.g. [{x:1,y:2},{x:3,y:4}] or [1,2,3,4] - */ - - /** - * get points array - * @name getPoints - * @method - * @memberof Kinetic.Polygon.prototype - * @returns {Array} - */ -})(); diff --git a/src/shapes/Spline.js b/src/shapes/Spline.js deleted file mode 100644 index 991add62..00000000 --- a/src/shapes/Spline.js +++ /dev/null @@ -1,115 +0,0 @@ -(function() { - /** - * Spline constructor.  Splines are defined by an array of points and - * a tension - * @constructor - * @memberof Kinetic - * @augments Kinetic.Shape - * @param {Object} config - * @param {Array} config.points can be a flattened array of points, an array of point arrays, or an array of point objects. - * e.g. [0,1,2,3], [[0,1],[2,3]] and [{x:0,y:1},{x:2,y:3}] are equivalent - * @param {Number} [config.tension] default value is 1. Higher values will result in a more curvy line. A value of 0 will result in no interpolation. - * @@shapeParams - * @@nodeParams - * @example - * var spline = new Kinetic.Spline({
- * x: 100,
- * y: 50,
- * points: [73, 70, 340, 23, 450, 60, 500, 20],
- * stroke: 'red',
- * tension: 1
- * }); - */ - Kinetic.Spline = function(config) { - this.___init(config); - }; - - Kinetic.Spline.prototype = { - ___init: function(config) { - var that = this; - // call super constructor - Kinetic.Shape.call(this, config); - this.className = 'Spline'; - - this.on('pointsChange.kinetic tensionChange.kinetic', function() { - that._setAllPoints(); - }); - - this._setAllPoints(); - }, - drawFunc: function(context) { - var points = this.getPoints(), - length = points.length, - tension = this.getTension(), - ap, len, n, point; - - context.beginPath(); - context.moveTo(points[0].x, points[0].y); - - // tension - if(tension !== 0 && length > 2) { - ap = this.allPoints; - len = ap.length; - n = 2; - - context.quadraticCurveTo(ap[0].x, ap[0].y, ap[1].x, ap[1].y); - - while(n < len - 1) { - context.bezierCurveTo(ap[n].x, ap[n++].y, ap[n].x, ap[n++].y, ap[n].x, ap[n++].y); - } - - context.quadraticCurveTo(ap[len - 1].x, ap[len - 1].y, points[length - 1].x, points[length - 1].y); - } - // no tension - else { - for(n = 1; n < length; n++) { - point = points[n]; - context.lineTo(point.x, point.y); - } - } - - context.strokeShape(this); - }, - _setAllPoints: function() { - this.allPoints = Kinetic.Util._expandPoints(this.getPoints(), this.getTension()); - } - }; - Kinetic.Util.extend(Kinetic.Spline, Kinetic.Shape); - - // add getters setters - Kinetic.Factory.addGetterSetter(Kinetic.Spline, 'tension', 1); - - /** - * get tension - * @name getTension - * @method - * @memberof Kinetic.Spline.prototype - * @returns {Number} - */ - - /** - * set tension - * @name setTension - * @method - * @memberof Kinetic.Spline.prototype - * @param {Number} tension - */ - - Kinetic.Factory.addPointsGetterSetter(Kinetic.Spline, 'points'); - /** - * get points array - * @name getPoints - * @method - * @memberof Kinetic.Spline.prototype - * @returns {Array} - */ - - /** - * set points array - * @name setPoints - * @method - * @memberof Kinetic.Spline.prototype - * @param {Array} can be an array of point objects or an array - * of Numbers. e.g. [{x:1,y:2},{x:3,y:4}] or [1,2,3,4] - */ -})(); diff --git a/test/unit/Node-test.js b/test/unit/Node-test.js index 5de474e8..ddc53554 100644 --- a/test/unit/Node-test.js +++ b/test/unit/Node-test.js @@ -912,12 +912,13 @@ suite('Node', function() { y: 93 }]; - var poly = new Kinetic.Polygon({ + var poly = new Kinetic.Line({ points: points, fill: 'green', stroke: 'blue', strokeWidth: 5, - draggable: true + draggable: true, + closed: true }); group.add(poly); diff --git a/test/unit/shapes/Blob-test.js b/test/unit/shapes/Blob-test.js index 60270381..b9591b63 100644 --- a/test/unit/shapes/Blob-test.js +++ b/test/unit/shapes/Blob-test.js @@ -4,7 +4,7 @@ suite('Blob', function(){ var stage = addStage(); var layer = new Kinetic.Layer(); - var blob = new Kinetic.Blob({ + var blob = new Kinetic.Line({ points: [{ x: 73, y: 140 @@ -22,7 +22,8 @@ suite('Blob', function(){ strokeWidth: 10, draggable: true, fill: '#aaf', - tension: 0.8 + tension: 0.8, + closed: true }); layer.add(blob); @@ -30,7 +31,7 @@ suite('Blob', function(){ assert.equal(blob.getTension(), 0.8); - assert.equal(blob.getClassName(), 'Blob'); + assert.equal(blob.getClassName(), 'Line'); //console.log(blob1.getPoints()) @@ -48,7 +49,7 @@ suite('Blob', function(){ var layer = new Kinetic.Layer(); - var blob = new Kinetic.Blob({ + var blob = new Kinetic.Line({ tension: 0.8, points: [{ x: 73, @@ -66,14 +67,15 @@ suite('Blob', function(){ stroke: 'blue', strokeWidth: 10, draggable: true, - fill: '#aaf' + fill: '#aaf', + closed: true }); layer.add(blob); stage.add(layer); - assert.equal(stage.find('Blob')[0].getPoints().length, 4); + assert.equal(stage.find('Line')[0].getPoints().length, 4); }); @@ -82,7 +84,7 @@ suite('Blob', function(){ var stage = addStage(); var layer = new Kinetic.Layer(); - var blob = new Kinetic.Blob({ + var blob = new Kinetic.Line({ points: [{ x: 73, y: 140 @@ -100,7 +102,8 @@ suite('Blob', function(){ strokeWidth: 10, draggable: true, fill: '#aaf', - tension: 0.8 + tension: 0.8, + closed: true }); layer.add(blob); diff --git a/test/unit/shapes/Line-test.js b/test/unit/shapes/Line-test.js index b716d7bf..2e83d354 100644 --- a/test/unit/shapes/Line-test.js +++ b/test/unit/shapes/Line-test.js @@ -18,7 +18,8 @@ suite('Line', function() { strokeWidth: 20, lineCap: 'round', lineJoin: 'round', - draggable: true + draggable: true, + tension: 0 }); layer.add(line); diff --git a/test/unit/shapes/Polygon-test.js b/test/unit/shapes/Polygon-test.js index 65b0f5b5..fb812db4 100644 --- a/test/unit/shapes/Polygon-test.js +++ b/test/unit/shapes/Polygon-test.js @@ -24,16 +24,17 @@ suite('Polygon', function() { y: 93 }]; - var poly = new Kinetic.Polygon({ + var poly = new Kinetic.Line({ points: points, fill: 'green', stroke: 'blue', - strokeWidth: 5 + strokeWidth: 5, + closed: true }); layer.add(poly); stage.add(layer); - assert.equal(poly.getClassName(), 'Polygon'); + assert.equal(poly.getClassName(), 'Line'); }); }); \ No newline at end of file diff --git a/test/unit/shapes/Spline-test.js b/test/unit/shapes/Spline-test.js index 2d4a2618..2d81f193 100644 --- a/test/unit/shapes/Spline-test.js +++ b/test/unit/shapes/Spline-test.js @@ -1,10 +1,10 @@ suite('Spline', function() { // ====================================================== - test('add spline', function() { + test('add splines', function() { var stage = addStage(); var layer = new Kinetic.Layer(); - var line1 = new Kinetic.Spline({ + var line1 = new Kinetic.Line({ points: [{ x: 73, y: 160 @@ -26,7 +26,7 @@ suite('Spline', function() { tension: 1 }); - var line2 = new Kinetic.Spline({ + var line2 = new Kinetic.Line({ points: [{ x: 73, y: 160 @@ -45,7 +45,7 @@ suite('Spline', function() { tension: 1 }); - var line3 = new Kinetic.Spline({ + var line3 = new Kinetic.Line({ points: [{ x: 73, y: 160 @@ -66,14 +66,12 @@ suite('Spline', function() { layer.add(line3); stage.add(layer); - assert.equal(line1.getClassName(), 'Spline'); + assert.equal(line1.getClassName(), 'Line'); var trace = layer.getContext().getTrace(); //console.log(trace); assert.equal(trace, 'clearRect(0,0,578,200);save();lineJoin=round;transform(1,0,0,1,0,0);beginPath();moveTo(73,160);quadraticCurveTo(74.006,54.77,340,23);bezierCurveTo(501.006,3.77,519.038,68.068,500,109);quadraticCurveTo(479.038,154.068,300,109);lineCap=round;lineWidth=10;strokeStyle=blue;stroke();restore();save();lineJoin=round;transform(1,0,0,1,0,0);beginPath();moveTo(73,160);quadraticCurveTo(74.006,54.77,340,23);quadraticCurveTo(501.006,3.77,500,109);lineCap=round;lineWidth=10;strokeStyle=red;stroke();restore();save();lineJoin=round;transform(1,0,0,1,0,0);beginPath();moveTo(73,160);lineTo(340,23);lineCap=round;lineWidth=10;strokeStyle=green;stroke();restore();'); - - }); // ====================================================== @@ -81,7 +79,7 @@ suite('Spline', function() { var stage = addStage(); var layer = new Kinetic.Layer(); - var spline = new Kinetic.Spline({ + var spline = new Kinetic.Line({ points: [{ x: 73, y: 160 @@ -107,7 +105,7 @@ suite('Spline', function() { layer.add(spline); stage.add(layer); - assert.equal(spline.allPoints.length, 6); + assert.equal(spline.getTensionPoints().length, 6); spline.setPoints([{ x: 73, @@ -120,7 +118,7 @@ suite('Spline', function() { y: 109 }]); - assert.equal(spline.allPoints.length, 3); + assert.equal(spline.getTensionPoints().length, 3); layer.draw(); @@ -132,7 +130,7 @@ suite('Spline', function() { var stage = addStage(); var layer = new Kinetic.Layer(); - var spline = new Kinetic.Spline({ + var spline = new Kinetic.Line({ points: [{ x: 73, y: 160 @@ -175,7 +173,7 @@ suite('Spline', function() { var stage = addStage(); var layer = new Kinetic.Layer(); - var line = new Kinetic.Spline({ + var line = new Kinetic.Line({ points: [ 73, 160, 340, 23, @@ -201,7 +199,7 @@ suite('Spline', function() { var stage = addStage(); var layer = new Kinetic.Layer(); - var line = new Kinetic.Spline({ + var line = new Kinetic.Line({ points: [{ x: 73, y: 160 @@ -234,7 +232,7 @@ suite('Spline', function() { var stage = addStage(); var layer = new Kinetic.Layer(); - var line = new Kinetic.Spline({ + var line = new Kinetic.Line({ points: [ [73, 160], [340, 23],