konva
Version:
<p align="center"> <img src="https://raw.githubusercontent.com/konvajs/konvajs.github.io/master/apple-touch-icon-180x180.png" alt="Konva logo" height="180" /> </p>
340 lines (339 loc) • 15.4 kB
JavaScript
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var Util_1 = require("../Util");
var Factory_1 = require("../Factory");
var Shape_1 = require("../Shape");
var Global_1 = require("../Global");
var Validators_1 = require("../Validators");
var Global_2 = require("../Global");
var AUTO = 'auto', CENTER = 'center', JUSTIFY = 'justify', CHANGE_KONVA = 'Change.konva', CONTEXT_2D = '2d', DASH = '-', LEFT = 'left', TEXT = 'text', TEXT_UPPER = 'Text', TOP = 'top', BOTTOM = 'bottom', MIDDLE = 'middle', NORMAL = 'normal', PX_SPACE = 'px ', SPACE = ' ', RIGHT = 'right', WORD = 'word', CHAR = 'char', NONE = 'none', ELLIPSIS = '…', ATTR_CHANGE_LIST = [
'fontFamily',
'fontSize',
'fontStyle',
'fontVariant',
'padding',
'align',
'verticalAlign',
'lineHeight',
'text',
'width',
'height',
'wrap',
'ellipsis',
'letterSpacing'
], attrChangeListLen = ATTR_CHANGE_LIST.length;
var dummyContext;
function getDummyContext() {
if (dummyContext) {
return dummyContext;
}
dummyContext = Util_1.Util.createCanvasElement().getContext(CONTEXT_2D);
return dummyContext;
}
function _fillFunc(context) {
context.fillText(this._partialText, this._partialTextX, this._partialTextY);
}
function _strokeFunc(context) {
context.strokeText(this._partialText, this._partialTextX, this._partialTextY);
}
function checkDefaultFill(config) {
config = config || {};
if (!config.fillLinearGradientColorStops &&
!config.fillRadialGradientColorStops &&
!config.fillPatternImage) {
config.fill = config.fill || 'black';
}
return config;
}
var Text = (function (_super) {
__extends(Text, _super);
function Text(config) {
var _this = _super.call(this, checkDefaultFill(config)) || this;
_this._partialTextX = 0;
_this._partialTextY = 0;
for (var n = 0; n < attrChangeListLen; n++) {
_this.on(ATTR_CHANGE_LIST[n] + CHANGE_KONVA, _this._setTextData);
}
_this._setTextData();
return _this;
}
Text.prototype._sceneFunc = function (context) {
var padding = this.padding(), fontSize = this.fontSize(), lineHeightPx = this.lineHeight() * fontSize, textArr = this.textArr, textArrLen = textArr.length, verticalAlign = this.verticalAlign(), alignY = 0, align = this.align(), totalWidth = this.getWidth(), letterSpacing = this.letterSpacing(), fill = this.fill(), textDecoration = this.textDecoration(), shouldUnderline = textDecoration.indexOf('underline') !== -1, shouldLineThrough = textDecoration.indexOf('line-through') !== -1, n;
var translateY = 0;
var translateY = lineHeightPx / 2;
var lineTranslateX = 0;
var lineTranslateY = 0;
context.setAttr('font', this._getContextFont());
context.setAttr('textBaseline', MIDDLE);
context.setAttr('textAlign', LEFT);
if (verticalAlign === MIDDLE) {
alignY = (this.getHeight() - textArrLen * lineHeightPx - padding * 2) / 2;
}
else if (verticalAlign === BOTTOM) {
alignY = this.getHeight() - textArrLen * lineHeightPx - padding * 2;
}
context.translate(padding, alignY + padding);
for (n = 0; n < textArrLen; n++) {
var lineTranslateX = 0;
var lineTranslateY = 0;
var obj = textArr[n], text = obj.text, width = obj.width, lastLine = n !== textArrLen - 1, spacesNumber, oneWord, lineWidth;
context.save();
if (align === RIGHT) {
lineTranslateX += totalWidth - width - padding * 2;
}
else if (align === CENTER) {
lineTranslateX += (totalWidth - width - padding * 2) / 2;
}
if (shouldUnderline) {
context.save();
context.beginPath();
context.moveTo(lineTranslateX, translateY + lineTranslateY + Math.round(fontSize / 2));
spacesNumber = text.split(' ').length - 1;
oneWord = spacesNumber === 0;
lineWidth =
align === JUSTIFY && lastLine && !oneWord
? totalWidth - padding * 2
: width;
context.lineTo(lineTranslateX + Math.round(lineWidth), translateY + lineTranslateY + Math.round(fontSize / 2));
context.lineWidth = fontSize / 15;
context.strokeStyle = fill;
context.stroke();
context.restore();
}
if (shouldLineThrough) {
context.save();
context.beginPath();
context.moveTo(lineTranslateX, translateY + lineTranslateY);
spacesNumber = text.split(' ').length - 1;
oneWord = spacesNumber === 0;
lineWidth =
align === JUSTIFY && lastLine && !oneWord
? totalWidth - padding * 2
: width;
context.lineTo(lineTranslateX + Math.round(lineWidth), translateY + lineTranslateY);
context.lineWidth = fontSize / 15;
context.strokeStyle = fill;
context.stroke();
context.restore();
}
if (letterSpacing !== 0 || align === JUSTIFY) {
spacesNumber = text.split(' ').length - 1;
for (var li = 0; li < text.length; li++) {
var letter = text[li];
if (letter === ' ' && n !== textArrLen - 1 && align === JUSTIFY) {
lineTranslateX += Math.floor((totalWidth - padding * 2 - width) / spacesNumber);
}
this._partialTextX = lineTranslateX;
this._partialTextY = translateY + lineTranslateY;
this._partialText = letter;
context.fillStrokeShape(this);
lineTranslateX +=
Math.round(this.measureSize(letter).width) + letterSpacing;
}
}
else {
this._partialTextX = lineTranslateX;
this._partialTextY = translateY + lineTranslateY;
this._partialText = text;
context.fillStrokeShape(this);
}
context.restore();
if (textArrLen > 1) {
translateY += lineHeightPx;
}
}
};
Text.prototype._hitFunc = function (context) {
var width = this.getWidth(), height = this.getHeight();
context.beginPath();
context.rect(0, 0, width, height);
context.closePath();
context.fillStrokeShape(this);
};
Text.prototype.setText = function (text) {
var str = Util_1.Util._isString(text) ? text : (text || '').toString();
this._setAttr(TEXT, str);
return this;
};
Text.prototype.getWidth = function () {
var isAuto = this.attrs.width === AUTO || this.attrs.width === undefined;
return isAuto ? this.getTextWidth() + this.padding() * 2 : this.attrs.width;
};
Text.prototype.getHeight = function () {
var isAuto = this.attrs.height === AUTO || this.attrs.height === undefined;
return isAuto
? this.fontSize() * this.textArr.length * this.lineHeight() +
this.padding() * 2
: this.attrs.height;
};
Text.prototype.getTextWidth = function () {
return this.textWidth;
};
Text.prototype.getTextHeight = function () {
Util_1.Util.warn('text.getTextHeight() method is deprecated. Use text.height() - for full height and text.fontSize() - for one line height.');
return this.textHeight;
};
Text.prototype.measureSize = function (text) {
var _context = getDummyContext(), fontSize = this.fontSize(), metrics;
_context.save();
_context.font = this._getContextFont();
metrics = _context.measureText(text);
_context.restore();
return {
width: metrics.width,
height: fontSize
};
};
Text.prototype._getContextFont = function () {
if (Global_1.Konva.UA.isIE) {
return (this.fontStyle() +
SPACE +
this.fontSize() +
PX_SPACE +
this.fontFamily());
}
return (this.fontStyle() +
SPACE +
this.fontVariant() +
SPACE +
this.fontSize() +
PX_SPACE +
this.fontFamily());
};
Text.prototype._addTextLine = function (line) {
if (this.align() === JUSTIFY) {
line = line.trim();
}
var width = this._getTextWidth(line);
return this.textArr.push({ text: line, width: width });
};
Text.prototype._getTextWidth = function (text) {
var letterSpacing = this.letterSpacing();
var length = text.length;
return (getDummyContext().measureText(text).width +
(length ? letterSpacing * (length - 1) : 0));
};
Text.prototype._setTextData = function () {
var lines = this.text().split('\n'), fontSize = +this.fontSize(), textWidth = 0, lineHeightPx = this.lineHeight() * fontSize, width = this.attrs.width, height = this.attrs.height, fixedWidth = width !== AUTO && width !== undefined, fixedHeight = height !== AUTO && height !== undefined, padding = this.padding(), maxWidth = width - padding * 2, maxHeightPx = height - padding * 2, currentHeightPx = 0, wrap = this.wrap(), shouldWrap = wrap !== NONE, wrapAtWord = wrap !== CHAR && shouldWrap, shouldAddEllipsis = this.ellipsis() && !shouldWrap;
this.textArr = [];
getDummyContext().font = this._getContextFont();
var additionalWidth = shouldAddEllipsis ? this._getTextWidth(ELLIPSIS) : 0;
for (var i = 0, max = lines.length; i < max; ++i) {
var line = lines[i];
var lineWidth = this._getTextWidth(line);
if (fixedWidth && lineWidth > maxWidth) {
while (line.length > 0) {
var low = 0, high = line.length, match = '', matchWidth = 0;
while (low < high) {
var mid = (low + high) >>> 1, substr = line.slice(0, mid + 1), substrWidth = this._getTextWidth(substr) + additionalWidth;
if (substrWidth <= maxWidth) {
low = mid + 1;
match = substr + (shouldAddEllipsis ? ELLIPSIS : '');
matchWidth = substrWidth;
}
else {
high = mid;
}
}
if (match) {
if (wrapAtWord) {
var wrapIndex;
var nextChar = line[match.length];
var nextIsSpaceOrDash = nextChar === SPACE || nextChar === DASH;
if (nextIsSpaceOrDash && matchWidth <= maxWidth) {
wrapIndex = match.length;
}
else {
wrapIndex =
Math.max(match.lastIndexOf(SPACE), match.lastIndexOf(DASH)) +
1;
}
if (wrapIndex > 0) {
low = wrapIndex;
match = match.slice(0, low);
matchWidth = this._getTextWidth(match);
}
}
match = match.trimRight();
this._addTextLine(match);
textWidth = Math.max(textWidth, matchWidth);
currentHeightPx += lineHeightPx;
if (!shouldWrap ||
(fixedHeight && currentHeightPx + lineHeightPx > maxHeightPx)) {
break;
}
line = line.slice(low);
line = line.trimLeft();
if (line.length > 0) {
lineWidth = this._getTextWidth(line);
if (lineWidth <= maxWidth) {
this._addTextLine(line);
currentHeightPx += lineHeightPx;
textWidth = Math.max(textWidth, lineWidth);
break;
}
}
}
else {
break;
}
}
}
else {
this._addTextLine(line);
currentHeightPx += lineHeightPx;
textWidth = Math.max(textWidth, lineWidth);
}
if (fixedHeight && currentHeightPx + lineHeightPx > maxHeightPx) {
break;
}
}
this.textHeight = fontSize;
this.textWidth = textWidth;
};
Text.prototype.getStrokeScaleEnabled = function () {
return true;
};
return Text;
}(Shape_1.Shape));
exports.Text = Text;
Text.prototype._fillFunc = _fillFunc;
Text.prototype._strokeFunc = _strokeFunc;
Text.prototype.className = TEXT_UPPER;
Text.prototype._attrsAffectingSize = [
'text',
'fontSize',
'padding',
'wrap',
'lineHeight'
];
Global_2._registerNode(Text);
Factory_1.Factory.overWriteSetter(Text, 'width', Validators_1.getNumberOrAutoValidator());
Factory_1.Factory.overWriteSetter(Text, 'height', Validators_1.getNumberOrAutoValidator());
Factory_1.Factory.addGetterSetter(Text, 'fontFamily', 'Arial');
Factory_1.Factory.addGetterSetter(Text, 'fontSize', 12, Validators_1.getNumberValidator());
Factory_1.Factory.addGetterSetter(Text, 'fontStyle', NORMAL);
Factory_1.Factory.addGetterSetter(Text, 'fontVariant', NORMAL);
Factory_1.Factory.addGetterSetter(Text, 'padding', 0, Validators_1.getNumberValidator());
Factory_1.Factory.addGetterSetter(Text, 'align', LEFT);
Factory_1.Factory.addGetterSetter(Text, 'verticalAlign', TOP);
Factory_1.Factory.addGetterSetter(Text, 'lineHeight', 1, Validators_1.getNumberValidator());
Factory_1.Factory.addGetterSetter(Text, 'wrap', WORD);
Factory_1.Factory.addGetterSetter(Text, 'ellipsis', false);
Factory_1.Factory.addGetterSetter(Text, 'letterSpacing', 0, Validators_1.getNumberValidator());
Factory_1.Factory.addGetterSetter(Text, 'text', '', Validators_1.getStringValidator());
Factory_1.Factory.addGetterSetter(Text, 'textDecoration', '');
Util_1.Collection.mapMethods(Text);