2012-03-07 13:45:48 +08:00
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
// Text
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
/**
|
|
|
|
* Text constructor
|
|
|
|
* @constructor
|
2012-07-02 07:25:02 +08:00
|
|
|
* @augments Kinetic.Shape
|
2012-03-07 13:45:48 +08:00
|
|
|
* @param {Object} config
|
|
|
|
*/
|
2012-08-23 14:35:21 +08:00
|
|
|
Kinetic.Text = function(config) {
|
|
|
|
this._initText(config);
|
|
|
|
};
|
|
|
|
|
|
|
|
Kinetic.Text.prototype = {
|
|
|
|
_initText: function(config) {
|
2012-07-04 03:07:27 +08:00
|
|
|
this.setDefaultAttrs({
|
|
|
|
fontFamily: 'Calibri',
|
|
|
|
text: '',
|
|
|
|
fontSize: 12,
|
|
|
|
align: 'left',
|
|
|
|
verticalAlign: 'top',
|
|
|
|
fontStyle: 'normal',
|
|
|
|
padding: 0,
|
|
|
|
width: 'auto',
|
|
|
|
height: 'auto',
|
|
|
|
detectionType: 'path',
|
|
|
|
cornerRadius: 0,
|
|
|
|
lineHeight: 1.2
|
|
|
|
});
|
|
|
|
|
|
|
|
this.dummyCanvas = document.createElement('canvas');
|
|
|
|
this.shapeType = "Text";
|
|
|
|
|
2012-07-29 01:46:16 +08:00
|
|
|
config.drawFunc = this.drawFunc;
|
2012-07-04 03:07:27 +08:00
|
|
|
// call super constructor
|
2012-08-23 14:35:21 +08:00
|
|
|
Kinetic.Shape.call(this, config);
|
2012-07-04 03:07:27 +08:00
|
|
|
|
|
|
|
// update text data for certain attr changes
|
2012-08-01 12:13:25 +08:00
|
|
|
var attrs = ['fontFamily', 'fontSize', 'fontStyle', 'padding', 'align', 'lineHeight', 'text', 'width', 'height'];
|
2012-07-04 03:07:27 +08:00
|
|
|
var that = this;
|
|
|
|
for(var n = 0; n < attrs.length; n++) {
|
|
|
|
var attr = attrs[n];
|
2012-07-08 05:43:12 +08:00
|
|
|
this.on(attr + 'Change.kinetic', that._setTextData);
|
2012-07-02 07:25:02 +08:00
|
|
|
}
|
2012-07-04 03:07:27 +08:00
|
|
|
that._setTextData();
|
|
|
|
},
|
2012-07-29 01:46:16 +08:00
|
|
|
drawFunc: function(context) {
|
|
|
|
// draw rect
|
|
|
|
context.beginPath();
|
|
|
|
var boxWidth = this.getBoxWidth();
|
|
|
|
var boxHeight = this.getBoxHeight();
|
|
|
|
|
|
|
|
if(this.attrs.cornerRadius === 0) {
|
|
|
|
// simple rect - don't bother doing all that complicated maths stuff.
|
|
|
|
context.rect(0, 0, boxWidth, boxHeight);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// arcTo would be nicer, but browser support is patchy (Opera)
|
|
|
|
context.moveTo(this.attrs.cornerRadius, 0);
|
|
|
|
context.lineTo(boxWidth - this.attrs.cornerRadius, 0);
|
|
|
|
context.arc(boxWidth - this.attrs.cornerRadius, this.attrs.cornerRadius, this.attrs.cornerRadius, Math.PI * 3 / 2, 0, false);
|
|
|
|
context.lineTo(boxWidth, boxHeight - this.attrs.cornerRadius);
|
|
|
|
context.arc(boxWidth - this.attrs.cornerRadius, boxHeight - this.attrs.cornerRadius, this.attrs.cornerRadius, 0, Math.PI / 2, false);
|
|
|
|
context.lineTo(this.attrs.cornerRadius, boxHeight);
|
|
|
|
context.arc(this.attrs.cornerRadius, boxHeight - this.attrs.cornerRadius, this.attrs.cornerRadius, Math.PI / 2, Math.PI, false);
|
|
|
|
context.lineTo(0, this.attrs.cornerRadius);
|
|
|
|
context.arc(this.attrs.cornerRadius, this.attrs.cornerRadius, this.attrs.cornerRadius, Math.PI, Math.PI * 3 / 2, false);
|
|
|
|
}
|
|
|
|
context.closePath();
|
|
|
|
|
|
|
|
this.fill(context);
|
|
|
|
this.stroke(context);
|
|
|
|
/*
|
|
|
|
* draw text
|
|
|
|
*/
|
|
|
|
var p = this.attrs.padding;
|
|
|
|
var lineHeightPx = this.attrs.lineHeight * this.getTextHeight();
|
|
|
|
var textArr = this.textArr;
|
|
|
|
|
|
|
|
context.font = this.attrs.fontStyle + ' ' + this.attrs.fontSize + 'pt ' + this.attrs.fontFamily;
|
|
|
|
context.textBaseline = 'middle';
|
|
|
|
context.textAlign = 'left';
|
|
|
|
context.save();
|
|
|
|
context.translate(p, 0);
|
|
|
|
context.translate(0, p + this.getTextHeight() / 2);
|
|
|
|
|
|
|
|
// draw text lines
|
2012-08-27 09:49:05 +08:00
|
|
|
var appliedShadow = this.appliedShadow;
|
2012-07-29 01:46:16 +08:00
|
|
|
for(var n = 0; n < textArr.length; n++) {
|
|
|
|
var text = textArr[n];
|
2012-08-27 09:49:05 +08:00
|
|
|
/*
|
|
|
|
* need to reset appliedShadow flag so that shadows
|
|
|
|
* are appropriately applied to each line of text
|
|
|
|
*/
|
|
|
|
this.appliedShadow = appliedShadow;
|
2012-07-29 01:46:16 +08:00
|
|
|
|
|
|
|
// horizontal alignment
|
|
|
|
context.save();
|
|
|
|
if(this.attrs.align === 'right') {
|
|
|
|
context.translate(this.getBoxWidth() - this._getTextSize(text).width - p * 2, 0);
|
|
|
|
}
|
|
|
|
else if(this.attrs.align === 'center') {
|
|
|
|
context.translate((this.getBoxWidth() - this._getTextSize(text).width - p * 2) / 2, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.fillText(context, text);
|
|
|
|
this.strokeText(context, text);
|
|
|
|
context.restore();
|
|
|
|
|
|
|
|
context.translate(0, lineHeightPx);
|
|
|
|
}
|
|
|
|
context.restore();
|
|
|
|
},
|
2012-04-01 06:40:27 +08:00
|
|
|
/**
|
2012-06-30 15:40:54 +08:00
|
|
|
* get box width
|
2012-07-09 12:56:52 +08:00
|
|
|
* @name getBoxWidth
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
2012-04-01 06:40:27 +08:00
|
|
|
*/
|
2012-06-30 15:40:54 +08:00
|
|
|
getBoxWidth: function() {
|
2012-07-02 07:29:15 +08:00
|
|
|
return this.attrs.width === 'auto' ? this.getTextWidth() + this.attrs.padding * 2 : this.attrs.width;
|
2012-06-30 15:40:54 +08:00
|
|
|
},
|
|
|
|
/**
|
|
|
|
* get box height
|
2012-07-09 12:56:52 +08:00
|
|
|
* @name getBoxHeight
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
2012-06-30 15:40:54 +08:00
|
|
|
*/
|
|
|
|
getBoxHeight: function() {
|
|
|
|
return this.attrs.height === 'auto' ? (this.getTextHeight() * this.textArr.length * this.attrs.lineHeight) + this.attrs.padding * 2 : this.attrs.height;
|
|
|
|
},
|
2012-07-09 12:56:52 +08:00
|
|
|
/**
|
|
|
|
* get text width in pixels
|
|
|
|
* @name getTextWidth
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
|
|
|
*/
|
|
|
|
getTextWidth: function() {
|
|
|
|
return this.textWidth;
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* get text height in pixels
|
|
|
|
* @name getTextHeight
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
|
|
|
*/
|
|
|
|
getTextHeight: function() {
|
|
|
|
return this.textHeight;
|
|
|
|
},
|
2012-06-30 15:40:54 +08:00
|
|
|
_getTextSize: function(text) {
|
|
|
|
var dummyCanvas = this.dummyCanvas;
|
2012-06-23 10:36:37 +08:00
|
|
|
var context = dummyCanvas.getContext('2d');
|
2012-05-13 06:45:04 +08:00
|
|
|
|
2012-04-01 06:40:27 +08:00
|
|
|
context.save();
|
2012-04-06 14:48:58 +08:00
|
|
|
context.font = this.attrs.fontStyle + ' ' + this.attrs.fontSize + 'pt ' + this.attrs.fontFamily;
|
2012-06-30 15:40:54 +08:00
|
|
|
var metrics = context.measureText(text);
|
2012-04-01 06:40:27 +08:00
|
|
|
context.restore();
|
|
|
|
return {
|
|
|
|
width: metrics.width,
|
2012-04-06 14:48:58 +08:00
|
|
|
height: parseInt(this.attrs.fontSize, 10)
|
2012-04-01 06:40:27 +08:00
|
|
|
};
|
2012-06-28 10:50:32 +08:00
|
|
|
},
|
2012-07-01 10:43:52 +08:00
|
|
|
/**
|
|
|
|
* set text data. wrap logic and width and height setting occurs
|
|
|
|
* here
|
|
|
|
*/
|
2012-06-30 15:40:54 +08:00
|
|
|
_setTextData: function() {
|
|
|
|
var charArr = this.attrs.text.split('');
|
|
|
|
var arr = [];
|
2012-07-01 10:43:52 +08:00
|
|
|
var row = 0;
|
2012-07-09 04:59:43 +08:00
|
|
|
var addLine = true;
|
2012-06-30 15:40:54 +08:00
|
|
|
this.textWidth = 0;
|
2012-07-02 08:14:15 +08:00
|
|
|
this.textHeight = this._getTextSize(this.attrs.text).height;
|
2012-07-01 10:43:52 +08:00
|
|
|
var lineHeightPx = this.attrs.lineHeight * this.textHeight;
|
2012-07-09 04:59:43 +08:00
|
|
|
while(charArr.length > 0 && addLine && (this.attrs.height === 'auto' || lineHeightPx * (row + 1) < this.attrs.height - this.attrs.padding * 2)) {
|
|
|
|
var index = 0;
|
|
|
|
var line = undefined;
|
|
|
|
addLine = false;
|
|
|
|
|
|
|
|
while(index < charArr.length) {
|
|
|
|
if(charArr.indexOf('\n') === index) {
|
|
|
|
// remove newline char
|
|
|
|
charArr.splice(index, 1);
|
|
|
|
line = charArr.splice(0, index).join('');
|
|
|
|
break;
|
|
|
|
}
|
2012-07-01 10:43:52 +08:00
|
|
|
|
2012-07-09 04:59:43 +08:00
|
|
|
// if line exceeds inner box width
|
|
|
|
var lineArr = charArr.slice(0, index);
|
|
|
|
if(this.attrs.width !== 'auto' && this._getTextSize(lineArr.join('')).width > this.attrs.width - this.attrs.padding * 2) {
|
|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
}
|
|
|
|
var lastSpace = lineArr.lastIndexOf(' ');
|
|
|
|
var lastDash = lineArr.lastIndexOf('-');
|
|
|
|
var wrapIndex = Math.max(lastSpace, lastDash);
|
|
|
|
if(wrapIndex >= 0) {
|
|
|
|
line = charArr.splice(0, 1 + wrapIndex).join('');
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* if not able to word wrap based on space or dash,
|
|
|
|
* go ahead and wrap in the middle of a word if needed
|
|
|
|
*/
|
|
|
|
line = charArr.splice(0, index).join('');
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
index++;
|
2012-06-30 15:40:54 +08:00
|
|
|
|
2012-07-09 04:59:43 +08:00
|
|
|
// if the end is reached
|
|
|
|
if(index === charArr.length) {
|
|
|
|
line = charArr.splice(0, index).join('');
|
|
|
|
}
|
|
|
|
}
|
2012-06-30 15:40:54 +08:00
|
|
|
this.textWidth = Math.max(this.textWidth, this._getTextSize(line).width);
|
2012-07-09 04:59:43 +08:00
|
|
|
if(line !== undefined) {
|
2012-07-01 10:43:52 +08:00
|
|
|
arr.push(line);
|
2012-07-09 04:59:43 +08:00
|
|
|
addLine = true;
|
2012-07-01 10:43:52 +08:00
|
|
|
}
|
|
|
|
row++;
|
2012-06-30 15:40:54 +08:00
|
|
|
}
|
|
|
|
this.textArr = arr;
|
2012-03-07 13:45:48 +08:00
|
|
|
}
|
2012-08-23 14:35:21 +08:00
|
|
|
};
|
|
|
|
Kinetic.Global.extend(Kinetic.Text, Kinetic.Shape);
|
|
|
|
|
2012-07-04 03:07:27 +08:00
|
|
|
// add getters setters
|
|
|
|
Kinetic.Node.addGettersSetters(Kinetic.Text, ['fontFamily', 'fontSize', 'fontStyle', 'textFill', 'textStroke', 'textStrokeWidth', 'padding', 'align', 'lineHeight', 'text', 'width', 'height', 'cornerRadius', 'fill', 'stroke', 'strokeWidth', 'shadow']);
|
2012-06-11 04:07:09 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* set font family
|
2012-06-14 17:19:51 +08:00
|
|
|
* @name setFontFamily
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
2012-06-11 04:07:09 +08:00
|
|
|
* @param {String} fontFamily
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* set font size
|
2012-06-14 17:19:51 +08:00
|
|
|
* @name setFontSize
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
2012-06-11 04:07:09 +08:00
|
|
|
* @param {int} fontSize
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* set font style. Can be "normal", "italic", or "bold". "normal" is the default.
|
2012-06-14 17:19:51 +08:00
|
|
|
* @name setFontStyle
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
2012-06-11 04:07:09 +08:00
|
|
|
* @param {String} fontStyle
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* set text fill color
|
2012-06-15 14:46:52 +08:00
|
|
|
* @name setTextFill
|
2012-06-14 17:19:51 +08:00
|
|
|
* @methodOf Kinetic.Text.prototype
|
2012-06-11 04:07:09 +08:00
|
|
|
* @param {String} textFill
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* set text stroke color
|
2012-06-14 17:19:51 +08:00
|
|
|
* @name setFontStroke
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
2012-06-11 04:07:09 +08:00
|
|
|
* @param {String} textStroke
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* set text stroke width
|
2012-06-14 17:19:51 +08:00
|
|
|
* @name setTextStrokeWidth
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
2012-06-11 04:07:09 +08:00
|
|
|
* @param {int} textStrokeWidth
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* set padding
|
2012-06-14 17:19:51 +08:00
|
|
|
* @name setPadding
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
2012-06-11 04:07:09 +08:00
|
|
|
* @param {int} padding
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* set horizontal align of text
|
2012-06-14 17:19:51 +08:00
|
|
|
* @name setAlign
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
2012-06-11 04:07:09 +08:00
|
|
|
* @param {String} align align can be 'left', 'center', or 'right'
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
2012-06-30 15:40:54 +08:00
|
|
|
* set line height
|
|
|
|
* @name setLineHeight
|
2012-06-14 17:19:51 +08:00
|
|
|
* @methodOf Kinetic.Text.prototype
|
2012-06-30 15:40:54 +08:00
|
|
|
* @param {Number} lineHeight default is 1.2
|
2012-06-11 04:07:09 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* set text
|
2012-06-14 17:19:51 +08:00
|
|
|
* @name setText
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
2012-06-11 04:07:09 +08:00
|
|
|
* @param {String} text
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
2012-06-28 10:50:32 +08:00
|
|
|
* set width of text box
|
2012-06-14 17:19:51 +08:00
|
|
|
* @name setWidth
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
2012-06-11 04:07:09 +08:00
|
|
|
* @param {Number} width
|
|
|
|
*/
|
|
|
|
|
2012-06-28 10:50:32 +08:00
|
|
|
/**
|
|
|
|
* set height of text box
|
|
|
|
* @name setHeight
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
|
|
|
* @param {Number} height
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* set shadow of text or textbox
|
|
|
|
* @name setShadow
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
|
|
|
* @param {Object} config
|
|
|
|
*/
|
|
|
|
|
2012-06-11 04:07:09 +08:00
|
|
|
/**
|
|
|
|
* get font family
|
2012-06-14 17:19:51 +08:00
|
|
|
* @name getFontFamily
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
2012-06-11 04:07:09 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get font size
|
2012-06-14 17:19:51 +08:00
|
|
|
* @name getFontSize
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
2012-06-11 04:07:09 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get font style
|
2012-06-14 17:19:51 +08:00
|
|
|
* @name getFontStyle
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
2012-06-11 04:07:09 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get text fill color
|
2012-06-14 17:19:51 +08:00
|
|
|
* @name getTextFill
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
2012-06-11 04:07:09 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get text stroke color
|
2012-06-14 17:19:51 +08:00
|
|
|
* @name getTextStroke
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
2012-06-11 04:07:09 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get text stroke width
|
2012-06-14 17:19:51 +08:00
|
|
|
* @name getTextStrokeWidth
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
2012-06-11 04:07:09 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get padding
|
2012-06-14 17:19:51 +08:00
|
|
|
* @name getPadding
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
2012-06-11 04:07:09 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get horizontal align
|
2012-06-14 17:19:51 +08:00
|
|
|
* @name getAlign
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
2012-06-11 04:07:09 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
2012-06-30 15:40:54 +08:00
|
|
|
* get line height
|
|
|
|
* @name getLineHeight
|
2012-06-14 17:19:51 +08:00
|
|
|
* @methodOf Kinetic.Text.prototype
|
2012-06-11 04:07:09 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get text
|
2012-06-14 17:19:51 +08:00
|
|
|
* @name getText
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
2012-06-11 04:07:09 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
2012-06-28 10:50:32 +08:00
|
|
|
* get width of text box
|
2012-06-14 17:19:51 +08:00
|
|
|
* @name getWidth
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
2012-06-28 10:50:32 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get height of text box
|
|
|
|
* @name getHeight
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get shadow of text or textbox
|
|
|
|
* @name getShadow
|
|
|
|
* @methodOf Kinetic.Text.prototype
|
2012-06-11 04:07:09 +08:00
|
|
|
*/
|