diff --git a/Thorfile b/Thorfile index 906d7afc..7610c1c4 100644 --- a/Thorfile +++ b/Thorfile @@ -14,6 +14,7 @@ class Build < Thor UNIT_TESTS = [ "tests/js/unit/animationTests.js", "tests/js/unit/globalTests.js", + "tests/js/unit/typeTests.js", "tests/js/unit/nodeTests.js", "tests/js/unit/stageTests.js", "tests/js/unit/containerTests.js", diff --git a/src/Node.js b/src/Node.js index 6927d798..d6f999ff 100644 --- a/src/Node.js +++ b/src/Node.js @@ -22,7 +22,12 @@ ON = 'on', OFF = 'off', BEFORE_DRAW = 'beforeDraw', - DRAW = 'draw'; + DRAW = 'draw', + BLACK = 'black', + RGB = 'RGB', + R = 'r', + G = 'g', + B = 'b'; /** * Node constructor. Nodes are entities that can be transformed, layered, @@ -1030,6 +1035,29 @@ this.addRotationGetter(constructor, attr, def); this.addRotationSetter(constructor, attr, isTransform); }; + Kinetic.Node.addColorGetterSetter = function(constructor, attr) { + this.addGetter(constructor, attr); + this.addSetter(constructor, attr); + + // components + this.addColorRGBGetter(constructor, attr); + this.addColorComponentGetter(constructor, attr, R); + this.addColorComponentGetter(constructor, attr, G); + this.addColorComponentGetter(constructor, attr, B); + }; + Kinetic.Node.addColorRGBGetter = function(constructor, attr) { + var method = GET + Kinetic.Type._capitalize(attr) + RGB; + constructor.prototype[method] = function() { + return Kinetic.Type.getRGB(this.attrs[attr]); + }; + }; + Kinetic.Node.addColorComponentGetter = function(constructor, attr, c) { + var baseMethod = GET + Kinetic.Type._capitalize(attr), + method = baseMethod + Kinetic.Type._capitalize(c); + constructor.prototype[method] = function() { + return this[baseMethod + RGB]()[c]; + }; + }; Kinetic.Node.addSetter = function(constructor, attr, isTransform) { var that = this, method = SET + Kinetic.Type._capitalize(attr); diff --git a/src/Shape.js b/src/Shape.js index 7dece24e..6f416206 100644 --- a/src/Shape.js +++ b/src/Shape.js @@ -218,18 +218,18 @@ Kinetic.Global.extend(Kinetic.Shape, Kinetic.Node); // add getters and setters - Kinetic.Node.addGetterSetter(Kinetic.Shape, 'stroke'); + Kinetic.Node.addColorGetterSetter(Kinetic.Shape, 'stroke'); Kinetic.Node.addGetterSetter(Kinetic.Shape, 'lineJoin'); Kinetic.Node.addGetterSetter(Kinetic.Shape, 'lineCap'); Kinetic.Node.addGetterSetter(Kinetic.Shape, 'strokeWidth'); Kinetic.Node.addGetterSetter(Kinetic.Shape, 'drawFunc'); Kinetic.Node.addGetterSetter(Kinetic.Shape, 'drawHitFunc'); Kinetic.Node.addGetterSetter(Kinetic.Shape, 'dashArray'); - Kinetic.Node.addGetterSetter(Kinetic.Shape, 'shadowColor'); + Kinetic.Node.addColorGetterSetter(Kinetic.Shape, 'shadowColor'); Kinetic.Node.addGetterSetter(Kinetic.Shape, 'shadowBlur'); Kinetic.Node.addGetterSetter(Kinetic.Shape, 'shadowOpacity'); Kinetic.Node.addGetterSetter(Kinetic.Shape, 'fillPatternImage'); - Kinetic.Node.addGetterSetter(Kinetic.Shape, 'fill'); + Kinetic.Node.addColorGetterSetter(Kinetic.Shape, 'fill'); Kinetic.Node.addGetterSetter(Kinetic.Shape, 'fillPatternX'); Kinetic.Node.addGetterSetter(Kinetic.Shape, 'fillPatternY'); Kinetic.Node.addGetterSetter(Kinetic.Shape, 'fillLinearGradientColorStops'); diff --git a/src/util/Type.js b/src/util/Type.js index f8c87f99..034d1526 100644 --- a/src/util/Type.js +++ b/src/util/Type.js @@ -6,8 +6,34 @@ OBJECT_NUMBER = '[object Number]', OBJECT_STRING = '[object String]', PI_OVER_DEG180 = Math.PI / 180, - DEG180_OVER_PI = 180 / Math.PI; - + DEG180_OVER_PI = 180 / Math.PI, + HASH = '#', + RGB_PAREN = 'rgb(', + COLORS = { + aqua: [0,255,255], + lime: [0,255,0], + silver: [192,192,192], + black: [0,0,0], + maroon: [128,0,0], + teal: [0,128,128], + blue: [0,0,255], + navy: [0,0,128], + white: [255,255,255], + fuchsia: [255,0,255], + olive:[128,128,0], + yellow: [255,255,0], + orange: [255,165,0], + gray: [128,128,128], + purple: [128,0,128], + green: [0,128,0], + red: [255,0,0], + pink: [255,192,203], + cyan: [0,255,255], + transparent: [255,255,255,0] + }, + + RGB_REGEX = /rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)/; + /* * utilities that handle data type detection, conversion, and manipulation */ @@ -298,6 +324,39 @@ } return randColor; }, + getRGB: function(color) { + var rgb; + // color string + if (color in COLORS) { + rgb = COLORS[color]; + return { + r: rgb[0], + g: rgb[1], + b: rgb[2] + }; + } + // hex + else if (color[0] === HASH) { + return this._hexToRgb(color.substring(1)); + } + // rgb string + else if (color.substr(0, 4) === RGB_PAREN) { + rgb = RGB_REGEX.exec(color.replace(/ /g,'')); + return { + r: parseInt(rgb[1]), + g: parseInt(rgb[2]), + b: parseInt(rgb[3]) + }; + } + // default + else { + return { + r: 0, + g: 0, + b: 0 + }; + } + }, // o1 takes precedence over o2 _merge: function(o1, o2) { var retObj = this._clone(o2); diff --git a/tests/js/unit/shapeTests.js b/tests/js/unit/shapeTests.js index ba350e0f..fe5a3b92 100644 --- a/tests/js/unit/shapeTests.js +++ b/tests/js/unit/shapeTests.js @@ -27,6 +27,62 @@ Test.Modules.SHAPE = { testDataUrl(layer.toDataURL(), 'scaled rect with disabled stroke scale', 'probem with stroke scale disabling'); }, + 'shape color components': function(containerId) { + var stage = new Kinetic.Stage({ + container: containerId, + width: 578, + height: 200 + }); + var layer = new Kinetic.Layer(); + var rect = new Kinetic.Rect({ + x: 200, + y: 90, + width: 100, + height: 50, + fill: 'green', + stroke: 'red' + + }); + + layer.add(rect); + stage.add(layer); + + // test component getters + test(rect.getFillRGB().r === 0, 'rect fill RGB.r should be 0'); + test(rect.getFillRGB().g === 128, 'rect fill RGB.g should be 128'); + test(rect.getFillRGB().b === 0, 'rect fill RGB.b should be 0'); + + test(rect.getFillR() === 0, 'rect fill r should be 0'); + test(rect.getFillG() === 128, 'rect fill g should be 128'); + test(rect.getFillB() === 0, 'rect fill b should be 0'); + + test(rect.getStrokeR() === 255, 'rect stroke r should be 255'); + test(rect.getStrokeG() === 0, 'rect stroke g should be 0'); + test(rect.getStrokeB() === 0, 'rect stroke b should be 0'); + + rect.setFill('#008000'); + rect.setStroke('#ff0000'); + + test(rect.getFillR() === 0, 'rect fill r should be 0'); + test(rect.getFillG() === 128, 'rect fill g should be 128'); + test(rect.getFillB() === 0, 'rect fill b should be 0'); + + test(rect.getStrokeR() === 255, 'rect stroke r should be 255'); + test(rect.getStrokeG() === 0, 'rect stroke g should be 0'); + test(rect.getStrokeB() === 0, 'rect stroke b should be 0'); + + rect.setFill('rgb(0,128,0)'); + rect.setStroke('rgb(255, 0, 0)'); + + test(rect.getFillR() === 0, 'rect fill r should be 0'); + test(rect.getFillG() === 128, 'rect fill g should be 128'); + test(rect.getFillB() === 0, 'rect fill b should be 0'); + + test(rect.getStrokeR() === 255, 'rect stroke r should be 255'); + test(rect.getStrokeG() === 0, 'rect stroke g should be 0'); + test(rect.getStrokeB() === 0, 'rect stroke b should be 0'); + }, + 'test intersects()': function(containerId) { var stage = new Kinetic.Stage({ container: containerId, diff --git a/tests/js/unit/typeTests.js b/tests/js/unit/typeTests.js new file mode 100644 index 00000000..49379326 --- /dev/null +++ b/tests/js/unit/typeTests.js @@ -0,0 +1,34 @@ +Test.Modules.TYPE = { + 'getRGB()': function() { + var rgb = {}; + + // color strings + rgb = Kinetic.Type.getRGB('red'); + test(rgb.r === 255, 'color string r should be 255'); + test(rgb.g === 0, 'color string g should be 0'); + test(rgb.b === 0, 'color string b should be 0'); + + rgb = Kinetic.Type.getRGB('pink'); + test(rgb.r === 255, 'color string r should be 255'); + test(rgb.g === 192, 'color string g should be 192'); + test(rgb.b === 203, 'color string b should be 203'); + + // hex + rgb = Kinetic.Type.getRGB('#00ff00'); + test(rgb.r === 0, 'hex r should be 0'); + test(rgb.g === 255, 'hex g should be 255'); + test(rgb.b === 0, 'hex b should be 0'); + + // rgb color string + rgb = Kinetic.Type.getRGB('rgb(255, 192, 203)'); + test(rgb.r === 255, 'rgb string r should be 255'); + test(rgb.g === 192, 'rgb string g should be 192'); + test(rgb.b === 203, 'rgb string b should be 203'); + + // default + rgb = Kinetic.Type.getRGB('not a color'); + test(rgb.r === 0, 'default r should be 0'); + test(rgb.g === 0, 'default g should be 0'); + test(rgb.b === 0, 'default b should be 0'); + } +}; \ No newline at end of file