2012-12-02 04:04:10 +08:00
|
|
|
(function() {
|
2013-02-11 07:42:48 +08:00
|
|
|
// constants
|
|
|
|
var AUTO = 'auto',
|
|
|
|
CALIBRI = 'Calibri',
|
|
|
|
CANVAS = 'canvas',
|
|
|
|
CENTER = 'center',
|
|
|
|
CHANGE_KINETIC = 'Change.kinetic',
|
|
|
|
CONTEXT_2D = '2d',
|
|
|
|
DASH = '\n',
|
|
|
|
EMPTY_STRING = '',
|
|
|
|
LEFT = 'left',
|
|
|
|
NEW_LINE = '\n',
|
|
|
|
TEXT = 'text',
|
|
|
|
TEXT_UPPER = 'Text',
|
|
|
|
TOP = 'top',
|
|
|
|
MIDDLE = 'middle',
|
|
|
|
NORMAL = 'normal',
|
|
|
|
PX_SPACE = 'px ',
|
|
|
|
SPACE = ' ',
|
|
|
|
RIGHT = 'right',
|
|
|
|
ATTR_CHANGE_LIST = ['fontFamily', 'fontSize', 'fontStyle', 'padding', 'align', 'lineHeight', 'text', 'width', 'height'],
|
|
|
|
|
|
|
|
// cached variables
|
|
|
|
attrChangeListLen = ATTR_CHANGE_LIST.length;
|
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
/**
|
|
|
|
* Text constructor
|
|
|
|
* @constructor
|
|
|
|
* @augments Kinetic.Shape
|
|
|
|
* @param {Object} config
|
2013-01-03 15:55:56 +08:00
|
|
|
* @param {String} [config.fontFamily] default is Calibri
|
|
|
|
* @param {Number} [config.fontSize] in pixels. Default is 12
|
|
|
|
* @param {String} [config.fontStyle] can be normal, bold, or italic. Default is normal
|
2012-12-23 15:08:03 +08:00
|
|
|
* @param {String} config.text
|
2013-01-03 15:55:56 +08:00
|
|
|
* @param {String} [config.align] can be left, center, or right
|
|
|
|
* @param {Number} [config.padding]
|
|
|
|
* @param {Number} [config.width] default is auto
|
|
|
|
* @param {Number} [config.height] default is auto
|
|
|
|
* @param {Number} [config.lineHeight] default is 1
|
2013-01-27 12:42:19 +08:00
|
|
|
* {{ShapeParams}}
|
|
|
|
* {{NodeParams}}
|
2012-12-02 04:04:10 +08:00
|
|
|
*/
|
|
|
|
Kinetic.Text = function(config) {
|
|
|
|
this._initText(config);
|
|
|
|
};
|
2013-01-25 14:44:00 +08:00
|
|
|
function _fillFunc(context) {
|
|
|
|
context.fillText(this.partialText, 0, 0);
|
|
|
|
}
|
|
|
|
function _strokeFunc(context) {
|
|
|
|
context.strokeText(this.partialText, 0, 0);
|
|
|
|
}
|
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
Kinetic.Text.prototype = {
|
|
|
|
_initText: function(config) {
|
2013-02-11 07:42:48 +08:00
|
|
|
var that = this;
|
2012-12-02 04:04:10 +08:00
|
|
|
this.setDefaultAttrs({
|
2013-02-11 07:42:48 +08:00
|
|
|
fontFamily: CALIBRI,
|
|
|
|
text: EMPTY_STRING,
|
2012-12-02 04:04:10 +08:00
|
|
|
fontSize: 12,
|
2013-02-11 07:42:48 +08:00
|
|
|
align: LEFT,
|
|
|
|
verticalAlign: TOP,
|
|
|
|
fontStyle: NORMAL,
|
2012-12-02 04:04:10 +08:00
|
|
|
padding: 0,
|
2013-02-11 07:42:48 +08:00
|
|
|
width: AUTO,
|
|
|
|
height: AUTO,
|
2013-01-02 11:36:13 +08:00
|
|
|
lineHeight: 1
|
2012-12-02 04:04:10 +08:00
|
|
|
});
|
|
|
|
|
2013-02-11 07:42:48 +08:00
|
|
|
this.dummyCanvas = document.createElement(CANVAS);
|
2013-01-25 14:44:00 +08:00
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
// call super constructor
|
|
|
|
Kinetic.Shape.call(this, config);
|
2013-01-25 14:44:00 +08:00
|
|
|
|
|
|
|
this._fillFunc = _fillFunc;
|
|
|
|
this._strokeFunc = _strokeFunc;
|
2013-02-11 07:42:48 +08:00
|
|
|
this.shapeType = TEXT_UPPER;
|
2012-12-02 04:04:10 +08:00
|
|
|
this._setDrawFuncs();
|
|
|
|
|
|
|
|
// update text data for certain attr changes
|
2013-02-11 07:42:48 +08:00
|
|
|
for(var n = 0; n < attrChangeListLen; n++) {
|
|
|
|
this.on(ATTR_CHANGE_LIST[n] + CHANGE_KINETIC, that._setTextData);
|
2012-07-29 01:46:16 +08:00
|
|
|
}
|
2013-01-25 14:44:00 +08:00
|
|
|
|
2013-02-11 07:42:48 +08:00
|
|
|
this._setTextData();
|
2012-12-02 04:04:10 +08:00
|
|
|
},
|
2012-12-10 01:52:33 +08:00
|
|
|
drawFunc: function(canvas) {
|
2013-02-11 07:42:48 +08:00
|
|
|
var context = canvas.getContext(),
|
|
|
|
p = this.getPadding(),
|
|
|
|
fontStyle = this.getFontStyle(),
|
|
|
|
fontSize = this.getFontSize(),
|
|
|
|
fontFamily = this.getFontFamily(),
|
|
|
|
textHeight = this.getTextHeight(),
|
|
|
|
lineHeightPx = this.getLineHeight() * textHeight,
|
|
|
|
textArr = this.textArr,
|
|
|
|
textArrLen = textArr.length,
|
|
|
|
width = this.getWidth();
|
2012-12-02 04:04:10 +08:00
|
|
|
|
2013-02-11 07:42:48 +08:00
|
|
|
context.font = fontStyle + SPACE + fontSize + PX_SPACE + fontFamily;
|
|
|
|
context.textBaseline = MIDDLE;
|
|
|
|
context.textAlign = LEFT;
|
2012-12-02 04:04:10 +08:00
|
|
|
context.save();
|
|
|
|
context.translate(p, 0);
|
2013-02-11 07:42:48 +08:00
|
|
|
context.translate(0, p + textHeight / 2);
|
2013-01-25 14:44:00 +08:00
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
// draw text lines
|
2013-02-11 07:42:48 +08:00
|
|
|
for(var n = 0; n < textArrLen; n++) {
|
2012-12-02 04:04:10 +08:00
|
|
|
var text = textArr[n];
|
|
|
|
|
|
|
|
// horizontal alignment
|
|
|
|
context.save();
|
2013-02-11 07:42:48 +08:00
|
|
|
if(this.getAlign() === RIGHT) {
|
|
|
|
context.translate(width - this._getTextSize(text).width - p * 2, 0);
|
2012-12-02 04:04:10 +08:00
|
|
|
}
|
2013-02-11 07:42:48 +08:00
|
|
|
else if(this.getAlign() === CENTER) {
|
|
|
|
context.translate((width - this._getTextSize(text).width - p * 2) / 2, 0);
|
2012-12-02 04:04:10 +08:00
|
|
|
}
|
|
|
|
|
2013-01-25 14:44:00 +08:00
|
|
|
this.partialText = text;
|
|
|
|
canvas.fillStroke(this);
|
2012-12-02 04:04:10 +08:00
|
|
|
context.restore();
|
|
|
|
context.translate(0, lineHeightPx);
|
2012-07-29 01:46:16 +08:00
|
|
|
}
|
2012-12-02 04:04:10 +08:00
|
|
|
context.restore();
|
|
|
|
},
|
2013-01-01 04:45:32 +08:00
|
|
|
drawHitFunc: function(canvas) {
|
2013-02-11 07:42:48 +08:00
|
|
|
var context = canvas.getContext(),
|
|
|
|
width = this.getWidth(),
|
|
|
|
height = this.getHeight();
|
2013-01-25 14:44:00 +08:00
|
|
|
|
2013-01-01 04:45:32 +08:00
|
|
|
context.beginPath();
|
2013-01-25 14:44:00 +08:00
|
|
|
context.rect(0, 0, width, height);
|
|
|
|
context.closePath();
|
2013-01-01 04:45:32 +08:00
|
|
|
canvas.fillStroke(this);
|
|
|
|
},
|
2012-12-02 04:04:10 +08:00
|
|
|
/**
|
|
|
|
* set text
|
|
|
|
* @name setText
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
|
|
|
* @param {String} text
|
|
|
|
*/
|
|
|
|
setText: function(text) {
|
|
|
|
var str = Kinetic.Type._isString(text) ? text : text.toString();
|
2013-02-11 07:42:48 +08:00
|
|
|
this.setAttr(TEXT, str);
|
2012-12-02 04:04:10 +08:00
|
|
|
},
|
|
|
|
/**
|
|
|
|
* get width
|
|
|
|
* @name getWidth
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
|
|
|
*/
|
|
|
|
getWidth: function() {
|
2013-02-11 07:42:48 +08:00
|
|
|
return this.attrs.width === AUTO ? this.getTextWidth() + this.getPadding() * 2 : this.attrs.width;
|
2012-12-02 04:04:10 +08:00
|
|
|
},
|
|
|
|
/**
|
|
|
|
* get height
|
|
|
|
* @name getHeight
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
|
|
|
*/
|
|
|
|
getHeight: function() {
|
2013-02-11 07:42:48 +08:00
|
|
|
return this.attrs.height === AUTO ? (this.getTextHeight() * this.textArr.length * this.attrs.lineHeight) + this.attrs.padding * 2 : this.attrs.height;
|
2012-12-02 04:04:10 +08:00
|
|
|
},
|
|
|
|
/**
|
|
|
|
* get text width
|
|
|
|
* @name getTextWidth
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
|
|
|
*/
|
|
|
|
getTextWidth: function() {
|
|
|
|
return this.textWidth;
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* get text height
|
|
|
|
* @name getTextHeight
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
|
|
|
*/
|
|
|
|
getTextHeight: function() {
|
|
|
|
return this.textHeight;
|
|
|
|
},
|
|
|
|
_getTextSize: function(text) {
|
2013-02-11 07:42:48 +08:00
|
|
|
var dummyCanvas = this.dummyCanvas,
|
|
|
|
context = dummyCanvas.getContext(CONTEXT_2D),
|
|
|
|
fontSize = this.getFontSize(),
|
|
|
|
metrics;
|
2012-07-29 01:46:16 +08:00
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
context.save();
|
2013-02-11 07:42:48 +08:00
|
|
|
context.font = this.getFontStyle() + SPACE + fontSize + PX_SPACE + this.getFontFamily();
|
|
|
|
|
|
|
|
metrics = context.measureText(text);
|
2012-07-29 01:46:16 +08:00
|
|
|
context.restore();
|
2012-12-02 04:04:10 +08:00
|
|
|
return {
|
|
|
|
width: metrics.width,
|
2013-02-11 07:42:48 +08:00
|
|
|
height: parseInt(fontSize, 10)
|
2012-12-02 04:04:10 +08:00
|
|
|
};
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* set text data. wrap logic and width and height setting occurs
|
|
|
|
* here
|
|
|
|
*/
|
|
|
|
_setTextData: function() {
|
2013-02-11 07:42:48 +08:00
|
|
|
var charArr = this.getText().split(EMPTY_STRING),
|
|
|
|
arr = [],
|
|
|
|
row = 0;
|
|
|
|
addLine = true,
|
|
|
|
lineHeightPx = 0,
|
|
|
|
padding = this.getPadding();
|
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
this.textWidth = 0;
|
2013-02-11 07:42:48 +08:00
|
|
|
this.textHeight = this._getTextSize(this.getText()).height;
|
|
|
|
lineHeightPx = this.getLineHeight() * this.textHeight;
|
|
|
|
|
|
|
|
while(charArr.length > 0 && addLine && (this.attrs.height === AUTO || lineHeightPx * (row + 1) < this.attrs.height - padding * 2)) {
|
2012-12-02 04:04:10 +08:00
|
|
|
var index = 0;
|
|
|
|
var line = undefined;
|
|
|
|
addLine = false;
|
|
|
|
|
|
|
|
while(index < charArr.length) {
|
2013-02-11 07:42:48 +08:00
|
|
|
if(charArr.indexOf(NEW_LINE) === index) {
|
2012-12-02 04:04:10 +08:00
|
|
|
// remove newline char
|
|
|
|
charArr.splice(index, 1);
|
2013-02-11 07:42:48 +08:00
|
|
|
line = charArr.splice(0, index).join(EMPTY_STRING);
|
2012-12-02 04:04:10 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if line exceeds inner box width
|
|
|
|
var lineArr = charArr.slice(0, index);
|
2013-02-11 07:42:48 +08:00
|
|
|
if(this.attrs.width !== AUTO && this._getTextSize(lineArr.join(EMPTY_STRING)).width > this.attrs.width - padding * 2) {
|
2012-12-02 04:04:10 +08:00
|
|
|
/*
|
|
|
|
* if a single character is too large to fit inside
|
|
|
|
* the text box width, then break out of the loop
|
|
|
|
* and stop processing
|
|
|
|
*/
|
|
|
|
if(index == 0) {
|
|
|
|
break;
|
|
|
|
}
|
2013-02-11 07:42:48 +08:00
|
|
|
var lastSpace = lineArr.lastIndexOf(SPACE);
|
|
|
|
var lastDash = lineArr.lastIndexOf(DASH);
|
2012-12-02 04:04:10 +08:00
|
|
|
var wrapIndex = Math.max(lastSpace, lastDash);
|
|
|
|
if(wrapIndex >= 0) {
|
2013-02-11 07:42:48 +08:00
|
|
|
line = charArr.splice(0, 1 + wrapIndex).join(EMPTY_STRING);
|
2012-12-02 04:04:10 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* if not able to word wrap based on space or dash,
|
|
|
|
* go ahead and wrap in the middle of a word if needed
|
|
|
|
*/
|
2013-02-11 07:42:48 +08:00
|
|
|
line = charArr.splice(0, index).join(EMPTY_STRING);
|
2012-12-02 04:04:10 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
index++;
|
|
|
|
|
|
|
|
// if the end is reached
|
|
|
|
if(index === charArr.length) {
|
2013-02-11 07:42:48 +08:00
|
|
|
line = charArr.splice(0, index).join(EMPTY_STRING);
|
2012-12-02 04:04:10 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
this.textWidth = Math.max(this.textWidth, this._getTextSize(line).width);
|
|
|
|
if(line !== undefined) {
|
|
|
|
arr.push(line);
|
|
|
|
addLine = true;
|
|
|
|
}
|
|
|
|
row++;
|
|
|
|
}
|
|
|
|
this.textArr = arr;
|
2012-12-10 01:52:33 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
Kinetic.Global.extend(Kinetic.Text, Kinetic.Shape);
|
2012-12-02 04:04:10 +08:00
|
|
|
|
|
|
|
// add getters setters
|
2013-01-01 04:45:32 +08:00
|
|
|
Kinetic.Node.addGettersSetters(Kinetic.Text, ['fontFamily', 'fontSize', 'fontStyle', 'padding', 'align', 'lineHeight']);
|
2013-02-11 07:42:48 +08:00
|
|
|
Kinetic.Node.addGetters(Kinetic.Text, [TEXT]);
|
2012-09-25 11:34:23 +08:00
|
|
|
/**
|
2012-12-02 04:04:10 +08:00
|
|
|
* set font family
|
|
|
|
* @name setFontFamily
|
2012-11-21 15:03:24 +08:00
|
|
|
* @methodOf Kinetic.Text.prototype
|
2012-12-02 04:04:10 +08:00
|
|
|
* @param {String} fontFamily
|
2012-11-21 15:03:24 +08:00
|
|
|
*/
|
2012-12-02 04:04:10 +08:00
|
|
|
|
2012-04-01 06:40:27 +08:00
|
|
|
/**
|
2013-01-02 11:36:13 +08:00
|
|
|
* set font size in pixels
|
2012-12-02 04:04:10 +08:00
|
|
|
* @name setFontSize
|
2012-07-09 12:56:52 +08:00
|
|
|
* @methodOf Kinetic.Text.prototype
|
2012-12-02 04:04:10 +08:00
|
|
|
* @param {int} fontSize
|
2012-04-01 06:40:27 +08:00
|
|
|
*/
|
2012-12-02 04:04:10 +08:00
|
|
|
|
2012-06-30 15:40:54 +08:00
|
|
|
/**
|
2013-01-01 16:41:13 +08:00
|
|
|
* set font style. Can be 'normal', 'italic', or 'bold'. 'normal' is the default.
|
2012-12-02 04:04:10 +08:00
|
|
|
* @name setFontStyle
|
2012-07-09 12:56:52 +08:00
|
|
|
* @methodOf Kinetic.Text.prototype
|
2012-12-02 04:04:10 +08:00
|
|
|
* @param {String} fontStyle
|
2012-06-30 15:40:54 +08:00
|
|
|
*/
|
2012-12-02 04:04:10 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* set padding
|
|
|
|
* @name setPadding
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
|
|
|
* @param {int} padding
|
|
|
|
*/
|
2012-11-13 11:59:19 +08:00
|
|
|
|
2012-11-24 06:54:32 +08:00
|
|
|
/**
|
2012-12-02 04:04:10 +08:00
|
|
|
* set horizontal align of text
|
|
|
|
* @name setAlign
|
2012-11-24 06:54:32 +08:00
|
|
|
* @methodOf Kinetic.Text.prototype
|
2012-12-02 04:04:10 +08:00
|
|
|
* @param {String} align align can be 'left', 'center', or 'right'
|
2012-11-24 06:54:32 +08:00
|
|
|
*/
|
2012-12-02 04:04:10 +08:00
|
|
|
|
2012-07-01 10:43:52 +08:00
|
|
|
/**
|
2012-12-02 04:04:10 +08:00
|
|
|
* set line height
|
|
|
|
* @name setLineHeight
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
2013-01-02 11:36:13 +08:00
|
|
|
* @param {Number} lineHeight default is 1
|
2012-07-01 10:43:52 +08:00
|
|
|
*/
|
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
/**
|
|
|
|
* get font family
|
|
|
|
* @name getFontFamily
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
|
|
|
*/
|
2012-06-30 15:40:54 +08:00
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
/**
|
|
|
|
* get font size
|
|
|
|
* @name getFontSize
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
|
|
|
*/
|
2012-11-24 06:54:32 +08:00
|
|
|
|
2012-12-02 04:04:10 +08:00
|
|
|
/**
|
|
|
|
* get font style
|
|
|
|
* @name getFontStyle
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get padding
|
|
|
|
* @name getPadding
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get horizontal align
|
|
|
|
* @name getAlign
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get line height
|
|
|
|
* @name getLineHeight
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get text
|
|
|
|
* @name getText
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
|
|
|
*/
|
|
|
|
})();
|