diff --git a/src/plugins/Label.js b/src/plugins/Label.js index 21802dce..c0443756 100644 --- a/src/plugins/Label.js +++ b/src/plugins/Label.js @@ -1,24 +1,20 @@ (function() { // constants - var ATTR_CHANGE_LIST = ['fontFamily', 'fontSize', 'fontStyle', 'padding', 'lineHeight', 'text'], - CHANGE_KINETIC = 'Change.kinetic', - NONE = 'none', - TOP = 'top', + var NONE = 'none', + UP = 'up', RIGHT = 'right', - BOTTOM = 'bottom', + DOWN = 'down', LEFT = 'left'; - - // cached variables - attrChangeListLen = ATTR_CHANGE_LIST.length; - + /** * Label constructor.  Blobs are defined by an array of points and * a tension * @constructor * @param {Object} config - * @param {String} [config.arrow] can be none, top, right, bottom, or left. none is the default - * @param {Number} [config.arrowWidth] - * @param {Number} [config.arrowHeight] + * @param {String} [config.pointerDirection] can be none, up, right, down, or left. none is the default + * @param {Number} [config.pointerWidth] + * @param {Number} [config.pointerHeight] + @param {Number} [config.cornerRadius] default is 0 * @param {Object} config.text * @param {Object} config.rect * @param {String} [config.text.fontFamily] default is Calibri @@ -27,10 +23,7 @@ * @param {String} config.text.text * @param {String} [config.text.align] can be left, center, or right * @param {Number} [config.text.padding] - * @param {Number} [config.text.width] default is auto - * @param {Number} [config.text.height] default is auto - * @param {Number} [config.rect.lineHeight] default is 1 - * {{ShapeParams}} + * @param {Number} [config.text.lineHeight] default is 1 * {{NodeParams}} */ Kinetic.Plugins.Label = function(config) { @@ -39,85 +32,120 @@ Kinetic.Plugins.Label.prototype = { _initLabel: function(config) { - var that = this, - text = null; - + this.innerGroup = new Kinetic.Group(); this.createAttrs(); Kinetic.Group.call(this, config); this.setText(new Kinetic.Text(config.text)); - text = this.getText(); - this.setRect(new Kinetic.Polygon(config.rect)); - this.add(this.getRect()); - this.add(this.getText()); - - this._setPoints(); - - // update text data for certain attr changes - for(var n = 0; n < attrChangeListLen; n++) { - text.on(ATTR_CHANGE_LIST[n] + CHANGE_KINETIC, function() { - that._setPoints(); - }); - } + this.setRect(new Kinetic.Plugins.LabelRect(config.rect)); + this.getRect().text = this.getText(); + this.innerGroup.add(this.getRect()); + this.innerGroup.add(this.getText()); + this.add(this.innerGroup); + + this._setGroupOffset(); }, - _setPoints: function() { + _setGroupOffset: function() { var text = this.getText(), width = text.getWidth(), height = text.getHeight(), - points = [], - arrow = this.getArrow(), - arrowWidth = this.getArrowWidth(), - arrowHeight = this.getArrowHeight(); - - // top left corner - points.push(0); - points.push(0); - - - if (arrow === TOP) { - points.push((width - arrowWidth)/2, 0); - points.push(width/2, -1 * arrowHeight); - points.push((width + arrowWidth)/2, 0); - } - - // top right - points.push(width); - points.push(0); + rect = this.getRect(), + pointerDirection = rect.getPointerDirection(), + pointerWidth = rect.getPointerWidth(), + pointerHeight = rect.getPointerHeight(), + x = 0, + y = 0; - if (arrow === RIGHT) { - points.push(width, (height - arrowHeight)/2); - points.push(width + arrowWidth, height/2); - points.push(width, (height + arrowHeight)/2); - } - - // bottom right - points.push(width); - points.push(height); - - if (arrow === BOTTOM) { - points.push((width + arrowWidth)/2, height); - points.push(width/2, height + arrowHeight); - points.push((width - arrowWidth)/2, height); - } - - // bottom left - points.push(0); - points.push(height); - - if (arrow === LEFT) { - points.push(0, (height + arrowHeight)/2); - points.push(0 - arrowWidth, height/2); - points.push(0, (height - arrowHeight)/2); - } - - this.getRect().setPoints(points); + switch(pointerDirection) { + case UP: + x = width / 2; + y = -1 * pointerHeight; + break; + case RIGHT: + x = width + pointerWidth; + y = height / 2; + break; + case DOWN: + x = width / 2; + y = height + pointerHeight; + break; + case LEFT: + x = -1 * pointerWidth; + y = height / 2; + break; + } + + this.setOffset({ + x: x, + y: y + }); } }; Kinetic.Global.extend(Kinetic.Plugins.Label, Kinetic.Group); - Kinetic.Node.addGetterSetter(Kinetic.Plugins.Label, 'text'); Kinetic.Node.addGetterSetter(Kinetic.Plugins.Label, 'rect'); - Kinetic.Node.addGetterSetter(Kinetic.Plugins.Label, 'arrow', NONE); - Kinetic.Node.addGetterSetter(Kinetic.Plugins.Label, 'arrowWidth', 0); - Kinetic.Node.addGetterSetter(Kinetic.Plugins.Label, 'arrowHeight', 0); -})(); + + Kinetic.Plugins.LabelRect = function(config) { + this._initLabelRect(config); + }; + + Kinetic.Plugins.LabelRect.prototype = { + _initLabelRect: function(config) { + this.createAttrs(); + Kinetic.Shape.call(this, config); + this.shapeType = 'LabelRect'; + this._setDrawFuncs(); + }, + drawFunc: function(canvas) { + var context = canvas.getContext(), + width = this.text.getWidth(), + height = this.text.getHeight(), + pointerDirection = this.getPointerDirection(), + pointerWidth = this.getPointerWidth(), + pointerHeight = this.getPointerHeight(), + cornerRadius = this.getCornerRadius(); + + context.beginPath(); + context.moveTo(0,0); + + if (pointerDirection === UP) { + context.lineTo((width - pointerWidth)/2, 0); + context.lineTo(width/2, -1 * pointerHeight); + context.lineTo((width + pointerWidth)/2, 0); + } + + context.lineTo(width, 0); + + if (pointerDirection === RIGHT) { + context.lineTo(width, (height - pointerHeight)/2); + context.lineTo(width + pointerWidth, height/2); + context.lineTo(width, (height + pointerHeight)/2); + } + + context.lineTo(width, height); + + if (pointerDirection === DOWN) { + context.lineTo((width + pointerWidth)/2, height); + context.lineTo(width/2, height + pointerHeight); + context.lineTo((width - pointerWidth)/2, height); + } + + context.lineTo(0, height); + + if (pointerDirection === LEFT) { + context.lineTo(0, (height + pointerHeight)/2); + context.lineTo(-1 * pointerWidth, height/2); + context.lineTo(0, (height - pointerHeight)/2); + } + + context.closePath(); + canvas.fillStroke(this); + } + }; + + Kinetic.Global.extend(Kinetic.Plugins.LabelRect, Kinetic.Shape); + Kinetic.Node.addGetterSetter(Kinetic.Plugins.LabelRect, 'pointerDirection', NONE); + Kinetic.Node.addGetterSetter(Kinetic.Plugins.LabelRect, 'pointerWidth', 0); + Kinetic.Node.addGetterSetter(Kinetic.Plugins.LabelRect, 'pointerHeight', 0); + Kinetic.Node.addGetterSetter(Kinetic.Plugins.LabelRect, 'cornerRadius', 0); +})(); \ No newline at end of file diff --git a/tests/js/unit/plugins/labelTests.js b/tests/js/unit/plugins/labelTests.js index 3e1bf0a2..af090acf 100644 --- a/tests/js/unit/plugins/labelTests.js +++ b/tests/js/unit/plugins/labelTests.js @@ -8,29 +8,30 @@ Test.Modules.LABEL = { var layer = new Kinetic.Layer(); var label = new Kinetic.Plugins.Label({ - x: 20, - y: 20, + x: 100, + y: 100, draggable: true, - arrow: 'left', - arrowWidth: 20, - arrowHeight: 20, - text: { + text: { text: 'Hello World!', fontSize: 50, fontFamily: 'Calibri', fontStyle: 'normal', lineHeight: 1.2, padding: 10, - fill: 'green', - }, + fill: 'green' + }, rect: { fill: '#bbb', stroke: '#333', shadowColor: 'black', - shadowBlur: 1, + shadowBlur: 10, shadowOffset: [10, 10], shadowOpacity: 0.2, - lineJoin: 'round' + lineJoin: 'round', + pointerDirection: 'down', + pointerWidth: 20, + pointerHeight: 20, + cornerRadius: 5 } });