UNPKG

22.7 kBJavaScriptView Raw
1import { __extends } from "tslib";
2import { parseRichText, parsePlainText } from './helper/parseText.js';
3import TSpan from './TSpan.js';
4import { retrieve2, each, normalizeCssArray, trim, retrieve3, extend, keys, defaults } from '../core/util.js';
5import { adjustTextX, adjustTextY } from '../contain/text.js';
6import ZRImage from './Image.js';
7import Rect from './shape/Rect.js';
8import BoundingRect from '../core/BoundingRect.js';
9import Displayable, { DEFAULT_COMMON_ANIMATION_PROPS } from './Displayable.js';
10import { DEFAULT_FONT, DEFAULT_FONT_SIZE } from '../core/platform.js';
11var DEFAULT_RICH_TEXT_COLOR = {
12 fill: '#000'
13};
14var DEFAULT_STROKE_LINE_WIDTH = 2;
15export var DEFAULT_TEXT_ANIMATION_PROPS = {
16 style: defaults({
17 fill: true,
18 stroke: true,
19 fillOpacity: true,
20 strokeOpacity: true,
21 lineWidth: true,
22 fontSize: true,
23 lineHeight: true,
24 width: true,
25 height: true,
26 textShadowColor: true,
27 textShadowBlur: true,
28 textShadowOffsetX: true,
29 textShadowOffsetY: true,
30 backgroundColor: true,
31 padding: true,
32 borderColor: true,
33 borderWidth: true,
34 borderRadius: true
35 }, DEFAULT_COMMON_ANIMATION_PROPS.style)
36};
37var ZRText = (function (_super) {
38 __extends(ZRText, _super);
39 function ZRText(opts) {
40 var _this = _super.call(this) || this;
41 _this.type = 'text';
42 _this._children = [];
43 _this._defaultStyle = DEFAULT_RICH_TEXT_COLOR;
44 _this.attr(opts);
45 return _this;
46 }
47 ZRText.prototype.childrenRef = function () {
48 return this._children;
49 };
50 ZRText.prototype.update = function () {
51 _super.prototype.update.call(this);
52 if (this.styleChanged()) {
53 this._updateSubTexts();
54 }
55 for (var i = 0; i < this._children.length; i++) {
56 var child = this._children[i];
57 child.zlevel = this.zlevel;
58 child.z = this.z;
59 child.z2 = this.z2;
60 child.culling = this.culling;
61 child.cursor = this.cursor;
62 child.invisible = this.invisible;
63 }
64 };
65 ZRText.prototype.updateTransform = function () {
66 var innerTransformable = this.innerTransformable;
67 if (innerTransformable) {
68 innerTransformable.updateTransform();
69 if (innerTransformable.transform) {
70 this.transform = innerTransformable.transform;
71 }
72 }
73 else {
74 _super.prototype.updateTransform.call(this);
75 }
76 };
77 ZRText.prototype.getLocalTransform = function (m) {
78 var innerTransformable = this.innerTransformable;
79 return innerTransformable
80 ? innerTransformable.getLocalTransform(m)
81 : _super.prototype.getLocalTransform.call(this, m);
82 };
83 ZRText.prototype.getComputedTransform = function () {
84 if (this.__hostTarget) {
85 this.__hostTarget.getComputedTransform();
86 this.__hostTarget.updateInnerText(true);
87 }
88 return _super.prototype.getComputedTransform.call(this);
89 };
90 ZRText.prototype._updateSubTexts = function () {
91 this._childCursor = 0;
92 normalizeTextStyle(this.style);
93 this.style.rich
94 ? this._updateRichTexts()
95 : this._updatePlainTexts();
96 this._children.length = this._childCursor;
97 this.styleUpdated();
98 };
99 ZRText.prototype.addSelfToZr = function (zr) {
100 _super.prototype.addSelfToZr.call(this, zr);
101 for (var i = 0; i < this._children.length; i++) {
102 this._children[i].__zr = zr;
103 }
104 };
105 ZRText.prototype.removeSelfFromZr = function (zr) {
106 _super.prototype.removeSelfFromZr.call(this, zr);
107 for (var i = 0; i < this._children.length; i++) {
108 this._children[i].__zr = null;
109 }
110 };
111 ZRText.prototype.getBoundingRect = function () {
112 if (this.styleChanged()) {
113 this._updateSubTexts();
114 }
115 if (!this._rect) {
116 var tmpRect = new BoundingRect(0, 0, 0, 0);
117 var children = this._children;
118 var tmpMat = [];
119 var rect = null;
120 for (var i = 0; i < children.length; i++) {
121 var child = children[i];
122 var childRect = child.getBoundingRect();
123 var transform = child.getLocalTransform(tmpMat);
124 if (transform) {
125 tmpRect.copy(childRect);
126 tmpRect.applyTransform(transform);
127 rect = rect || tmpRect.clone();
128 rect.union(tmpRect);
129 }
130 else {
131 rect = rect || childRect.clone();
132 rect.union(childRect);
133 }
134 }
135 this._rect = rect || tmpRect;
136 }
137 return this._rect;
138 };
139 ZRText.prototype.setDefaultTextStyle = function (defaultTextStyle) {
140 this._defaultStyle = defaultTextStyle || DEFAULT_RICH_TEXT_COLOR;
141 };
142 ZRText.prototype.setTextContent = function (textContent) {
143 if (process.env.NODE_ENV !== 'production') {
144 throw new Error('Can\'t attach text on another text');
145 }
146 };
147 ZRText.prototype._mergeStyle = function (targetStyle, sourceStyle) {
148 if (!sourceStyle) {
149 return targetStyle;
150 }
151 var sourceRich = sourceStyle.rich;
152 var targetRich = targetStyle.rich || (sourceRich && {});
153 extend(targetStyle, sourceStyle);
154 if (sourceRich && targetRich) {
155 this._mergeRich(targetRich, sourceRich);
156 targetStyle.rich = targetRich;
157 }
158 else if (targetRich) {
159 targetStyle.rich = targetRich;
160 }
161 return targetStyle;
162 };
163 ZRText.prototype._mergeRich = function (targetRich, sourceRich) {
164 var richNames = keys(sourceRich);
165 for (var i = 0; i < richNames.length; i++) {
166 var richName = richNames[i];
167 targetRich[richName] = targetRich[richName] || {};
168 extend(targetRich[richName], sourceRich[richName]);
169 }
170 };
171 ZRText.prototype.getAnimationStyleProps = function () {
172 return DEFAULT_TEXT_ANIMATION_PROPS;
173 };
174 ZRText.prototype._getOrCreateChild = function (Ctor) {
175 var child = this._children[this._childCursor];
176 if (!child || !(child instanceof Ctor)) {
177 child = new Ctor();
178 }
179 this._children[this._childCursor++] = child;
180 child.__zr = this.__zr;
181 child.parent = this;
182 return child;
183 };
184 ZRText.prototype._updatePlainTexts = function () {
185 var style = this.style;
186 var textFont = style.font || DEFAULT_FONT;
187 var textPadding = style.padding;
188 var text = getStyleText(style);
189 var contentBlock = parsePlainText(text, style);
190 var needDrawBg = needDrawBackground(style);
191 var bgColorDrawn = !!(style.backgroundColor);
192 var outerHeight = contentBlock.outerHeight;
193 var outerWidth = contentBlock.outerWidth;
194 var contentWidth = contentBlock.contentWidth;
195 var textLines = contentBlock.lines;
196 var lineHeight = contentBlock.lineHeight;
197 var defaultStyle = this._defaultStyle;
198 var baseX = style.x || 0;
199 var baseY = style.y || 0;
200 var textAlign = style.align || defaultStyle.align || 'left';
201 var verticalAlign = style.verticalAlign || defaultStyle.verticalAlign || 'top';
202 var textX = baseX;
203 var textY = adjustTextY(baseY, contentBlock.contentHeight, verticalAlign);
204 if (needDrawBg || textPadding) {
205 var boxX = adjustTextX(baseX, outerWidth, textAlign);
206 var boxY = adjustTextY(baseY, outerHeight, verticalAlign);
207 needDrawBg && this._renderBackground(style, style, boxX, boxY, outerWidth, outerHeight);
208 }
209 textY += lineHeight / 2;
210 if (textPadding) {
211 textX = getTextXForPadding(baseX, textAlign, textPadding);
212 if (verticalAlign === 'top') {
213 textY += textPadding[0];
214 }
215 else if (verticalAlign === 'bottom') {
216 textY -= textPadding[2];
217 }
218 }
219 var defaultLineWidth = 0;
220 var useDefaultFill = false;
221 var textFill = getFill('fill' in style
222 ? style.fill
223 : (useDefaultFill = true, defaultStyle.fill));
224 var textStroke = getStroke('stroke' in style
225 ? style.stroke
226 : (!bgColorDrawn
227 && (!defaultStyle.autoStroke || useDefaultFill))
228 ? (defaultLineWidth = DEFAULT_STROKE_LINE_WIDTH, defaultStyle.stroke)
229 : null);
230 var hasShadow = style.textShadowBlur > 0;
231 var fixedBoundingRect = style.width != null
232 && (style.overflow === 'truncate' || style.overflow === 'break' || style.overflow === 'breakAll');
233 var calculatedLineHeight = contentBlock.calculatedLineHeight;
234 for (var i = 0; i < textLines.length; i++) {
235 var el = this._getOrCreateChild(TSpan);
236 var subElStyle = el.createStyle();
237 el.useStyle(subElStyle);
238 subElStyle.text = textLines[i];
239 subElStyle.x = textX;
240 subElStyle.y = textY;
241 if (textAlign) {
242 subElStyle.textAlign = textAlign;
243 }
244 subElStyle.textBaseline = 'middle';
245 subElStyle.opacity = style.opacity;
246 subElStyle.strokeFirst = true;
247 if (hasShadow) {
248 subElStyle.shadowBlur = style.textShadowBlur || 0;
249 subElStyle.shadowColor = style.textShadowColor || 'transparent';
250 subElStyle.shadowOffsetX = style.textShadowOffsetX || 0;
251 subElStyle.shadowOffsetY = style.textShadowOffsetY || 0;
252 }
253 subElStyle.stroke = textStroke;
254 subElStyle.fill = textFill;
255 if (textStroke) {
256 subElStyle.lineWidth = style.lineWidth || defaultLineWidth;
257 subElStyle.lineDash = style.lineDash;
258 subElStyle.lineDashOffset = style.lineDashOffset || 0;
259 }
260 subElStyle.font = textFont;
261 setSeparateFont(subElStyle, style);
262 textY += lineHeight;
263 if (fixedBoundingRect) {
264 el.setBoundingRect(new BoundingRect(adjustTextX(subElStyle.x, style.width, subElStyle.textAlign), adjustTextY(subElStyle.y, calculatedLineHeight, subElStyle.textBaseline), contentWidth, calculatedLineHeight));
265 }
266 }
267 };
268 ZRText.prototype._updateRichTexts = function () {
269 var style = this.style;
270 var text = getStyleText(style);
271 var contentBlock = parseRichText(text, style);
272 var contentWidth = contentBlock.width;
273 var outerWidth = contentBlock.outerWidth;
274 var outerHeight = contentBlock.outerHeight;
275 var textPadding = style.padding;
276 var baseX = style.x || 0;
277 var baseY = style.y || 0;
278 var defaultStyle = this._defaultStyle;
279 var textAlign = style.align || defaultStyle.align;
280 var verticalAlign = style.verticalAlign || defaultStyle.verticalAlign;
281 var boxX = adjustTextX(baseX, outerWidth, textAlign);
282 var boxY = adjustTextY(baseY, outerHeight, verticalAlign);
283 var xLeft = boxX;
284 var lineTop = boxY;
285 if (textPadding) {
286 xLeft += textPadding[3];
287 lineTop += textPadding[0];
288 }
289 var xRight = xLeft + contentWidth;
290 if (needDrawBackground(style)) {
291 this._renderBackground(style, style, boxX, boxY, outerWidth, outerHeight);
292 }
293 var bgColorDrawn = !!(style.backgroundColor);
294 for (var i = 0; i < contentBlock.lines.length; i++) {
295 var line = contentBlock.lines[i];
296 var tokens = line.tokens;
297 var tokenCount = tokens.length;
298 var lineHeight = line.lineHeight;
299 var remainedWidth = line.width;
300 var leftIndex = 0;
301 var lineXLeft = xLeft;
302 var lineXRight = xRight;
303 var rightIndex = tokenCount - 1;
304 var token = void 0;
305 while (leftIndex < tokenCount
306 && (token = tokens[leftIndex], !token.align || token.align === 'left')) {
307 this._placeToken(token, style, lineHeight, lineTop, lineXLeft, 'left', bgColorDrawn);
308 remainedWidth -= token.width;
309 lineXLeft += token.width;
310 leftIndex++;
311 }
312 while (rightIndex >= 0
313 && (token = tokens[rightIndex], token.align === 'right')) {
314 this._placeToken(token, style, lineHeight, lineTop, lineXRight, 'right', bgColorDrawn);
315 remainedWidth -= token.width;
316 lineXRight -= token.width;
317 rightIndex--;
318 }
319 lineXLeft += (contentWidth - (lineXLeft - xLeft) - (xRight - lineXRight) - remainedWidth) / 2;
320 while (leftIndex <= rightIndex) {
321 token = tokens[leftIndex];
322 this._placeToken(token, style, lineHeight, lineTop, lineXLeft + token.width / 2, 'center', bgColorDrawn);
323 lineXLeft += token.width;
324 leftIndex++;
325 }
326 lineTop += lineHeight;
327 }
328 };
329 ZRText.prototype._placeToken = function (token, style, lineHeight, lineTop, x, textAlign, parentBgColorDrawn) {
330 var tokenStyle = style.rich[token.styleName] || {};
331 tokenStyle.text = token.text;
332 var verticalAlign = token.verticalAlign;
333 var y = lineTop + lineHeight / 2;
334 if (verticalAlign === 'top') {
335 y = lineTop + token.height / 2;
336 }
337 else if (verticalAlign === 'bottom') {
338 y = lineTop + lineHeight - token.height / 2;
339 }
340 var needDrawBg = !token.isLineHolder && needDrawBackground(tokenStyle);
341 needDrawBg && this._renderBackground(tokenStyle, style, textAlign === 'right'
342 ? x - token.width
343 : textAlign === 'center'
344 ? x - token.width / 2
345 : x, y - token.height / 2, token.width, token.height);
346 var bgColorDrawn = !!tokenStyle.backgroundColor;
347 var textPadding = token.textPadding;
348 if (textPadding) {
349 x = getTextXForPadding(x, textAlign, textPadding);
350 y -= token.height / 2 - textPadding[0] - token.innerHeight / 2;
351 }
352 var el = this._getOrCreateChild(TSpan);
353 var subElStyle = el.createStyle();
354 el.useStyle(subElStyle);
355 var defaultStyle = this._defaultStyle;
356 var useDefaultFill = false;
357 var defaultLineWidth = 0;
358 var textFill = getFill('fill' in tokenStyle ? tokenStyle.fill
359 : 'fill' in style ? style.fill
360 : (useDefaultFill = true, defaultStyle.fill));
361 var textStroke = getStroke('stroke' in tokenStyle ? tokenStyle.stroke
362 : 'stroke' in style ? style.stroke
363 : (!bgColorDrawn
364 && !parentBgColorDrawn
365 && (!defaultStyle.autoStroke || useDefaultFill)) ? (defaultLineWidth = DEFAULT_STROKE_LINE_WIDTH, defaultStyle.stroke)
366 : null);
367 var hasShadow = tokenStyle.textShadowBlur > 0
368 || style.textShadowBlur > 0;
369 subElStyle.text = token.text;
370 subElStyle.x = x;
371 subElStyle.y = y;
372 if (hasShadow) {
373 subElStyle.shadowBlur = tokenStyle.textShadowBlur || style.textShadowBlur || 0;
374 subElStyle.shadowColor = tokenStyle.textShadowColor || style.textShadowColor || 'transparent';
375 subElStyle.shadowOffsetX = tokenStyle.textShadowOffsetX || style.textShadowOffsetX || 0;
376 subElStyle.shadowOffsetY = tokenStyle.textShadowOffsetY || style.textShadowOffsetY || 0;
377 }
378 subElStyle.textAlign = textAlign;
379 subElStyle.textBaseline = 'middle';
380 subElStyle.font = token.font || DEFAULT_FONT;
381 subElStyle.opacity = retrieve3(tokenStyle.opacity, style.opacity, 1);
382 setSeparateFont(subElStyle, tokenStyle);
383 if (textStroke) {
384 subElStyle.lineWidth = retrieve3(tokenStyle.lineWidth, style.lineWidth, defaultLineWidth);
385 subElStyle.lineDash = retrieve2(tokenStyle.lineDash, style.lineDash);
386 subElStyle.lineDashOffset = style.lineDashOffset || 0;
387 subElStyle.stroke = textStroke;
388 }
389 if (textFill) {
390 subElStyle.fill = textFill;
391 }
392 var textWidth = token.contentWidth;
393 var textHeight = token.contentHeight;
394 el.setBoundingRect(new BoundingRect(adjustTextX(subElStyle.x, textWidth, subElStyle.textAlign), adjustTextY(subElStyle.y, textHeight, subElStyle.textBaseline), textWidth, textHeight));
395 };
396 ZRText.prototype._renderBackground = function (style, topStyle, x, y, width, height) {
397 var textBackgroundColor = style.backgroundColor;
398 var textBorderWidth = style.borderWidth;
399 var textBorderColor = style.borderColor;
400 var isImageBg = textBackgroundColor && textBackgroundColor.image;
401 var isPlainOrGradientBg = textBackgroundColor && !isImageBg;
402 var textBorderRadius = style.borderRadius;
403 var self = this;
404 var rectEl;
405 var imgEl;
406 if (isPlainOrGradientBg || style.lineHeight || (textBorderWidth && textBorderColor)) {
407 rectEl = this._getOrCreateChild(Rect);
408 rectEl.useStyle(rectEl.createStyle());
409 rectEl.style.fill = null;
410 var rectShape = rectEl.shape;
411 rectShape.x = x;
412 rectShape.y = y;
413 rectShape.width = width;
414 rectShape.height = height;
415 rectShape.r = textBorderRadius;
416 rectEl.dirtyShape();
417 }
418 if (isPlainOrGradientBg) {
419 var rectStyle = rectEl.style;
420 rectStyle.fill = textBackgroundColor || null;
421 rectStyle.fillOpacity = retrieve2(style.fillOpacity, 1);
422 }
423 else if (isImageBg) {
424 imgEl = this._getOrCreateChild(ZRImage);
425 imgEl.onload = function () {
426 self.dirtyStyle();
427 };
428 var imgStyle = imgEl.style;
429 imgStyle.image = textBackgroundColor.image;
430 imgStyle.x = x;
431 imgStyle.y = y;
432 imgStyle.width = width;
433 imgStyle.height = height;
434 }
435 if (textBorderWidth && textBorderColor) {
436 var rectStyle = rectEl.style;
437 rectStyle.lineWidth = textBorderWidth;
438 rectStyle.stroke = textBorderColor;
439 rectStyle.strokeOpacity = retrieve2(style.strokeOpacity, 1);
440 rectStyle.lineDash = style.borderDash;
441 rectStyle.lineDashOffset = style.borderDashOffset || 0;
442 rectEl.strokeContainThreshold = 0;
443 if (rectEl.hasFill() && rectEl.hasStroke()) {
444 rectStyle.strokeFirst = true;
445 rectStyle.lineWidth *= 2;
446 }
447 }
448 var commonStyle = (rectEl || imgEl).style;
449 commonStyle.shadowBlur = style.shadowBlur || 0;
450 commonStyle.shadowColor = style.shadowColor || 'transparent';
451 commonStyle.shadowOffsetX = style.shadowOffsetX || 0;
452 commonStyle.shadowOffsetY = style.shadowOffsetY || 0;
453 commonStyle.opacity = retrieve3(style.opacity, topStyle.opacity, 1);
454 };
455 ZRText.makeFont = function (style) {
456 var font = '';
457 if (hasSeparateFont(style)) {
458 font = [
459 style.fontStyle,
460 style.fontWeight,
461 parseFontSize(style.fontSize),
462 style.fontFamily || 'sans-serif'
463 ].join(' ');
464 }
465 return font && trim(font) || style.textFont || style.font;
466 };
467 return ZRText;
468}(Displayable));
469var VALID_TEXT_ALIGN = { left: true, right: 1, center: 1 };
470var VALID_TEXT_VERTICAL_ALIGN = { top: 1, bottom: 1, middle: 1 };
471var FONT_PARTS = ['fontStyle', 'fontWeight', 'fontSize', 'fontFamily'];
472export function parseFontSize(fontSize) {
473 if (typeof fontSize === 'string'
474 && (fontSize.indexOf('px') !== -1
475 || fontSize.indexOf('rem') !== -1
476 || fontSize.indexOf('em') !== -1)) {
477 return fontSize;
478 }
479 else if (!isNaN(+fontSize)) {
480 return fontSize + 'px';
481 }
482 else {
483 return DEFAULT_FONT_SIZE + 'px';
484 }
485}
486function setSeparateFont(targetStyle, sourceStyle) {
487 for (var i = 0; i < FONT_PARTS.length; i++) {
488 var fontProp = FONT_PARTS[i];
489 var val = sourceStyle[fontProp];
490 if (val != null) {
491 targetStyle[fontProp] = val;
492 }
493 }
494}
495export function hasSeparateFont(style) {
496 return style.fontSize != null || style.fontFamily || style.fontWeight;
497}
498export function normalizeTextStyle(style) {
499 normalizeStyle(style);
500 each(style.rich, normalizeStyle);
501 return style;
502}
503function normalizeStyle(style) {
504 if (style) {
505 style.font = ZRText.makeFont(style);
506 var textAlign = style.align;
507 textAlign === 'middle' && (textAlign = 'center');
508 style.align = (textAlign == null || VALID_TEXT_ALIGN[textAlign]) ? textAlign : 'left';
509 var verticalAlign = style.verticalAlign;
510 verticalAlign === 'center' && (verticalAlign = 'middle');
511 style.verticalAlign = (verticalAlign == null || VALID_TEXT_VERTICAL_ALIGN[verticalAlign]) ? verticalAlign : 'top';
512 var textPadding = style.padding;
513 if (textPadding) {
514 style.padding = normalizeCssArray(style.padding);
515 }
516 }
517}
518function getStroke(stroke, lineWidth) {
519 return (stroke == null || lineWidth <= 0 || stroke === 'transparent' || stroke === 'none')
520 ? null
521 : (stroke.image || stroke.colorStops)
522 ? '#000'
523 : stroke;
524}
525function getFill(fill) {
526 return (fill == null || fill === 'none')
527 ? null
528 : (fill.image || fill.colorStops)
529 ? '#000'
530 : fill;
531}
532function getTextXForPadding(x, textAlign, textPadding) {
533 return textAlign === 'right'
534 ? (x - textPadding[1])
535 : textAlign === 'center'
536 ? (x + textPadding[3] / 2 - textPadding[1] / 2)
537 : (x + textPadding[3]);
538}
539function getStyleText(style) {
540 var text = style.text;
541 text != null && (text += '');
542 return text;
543}
544function needDrawBackground(style) {
545 return !!(style.backgroundColor
546 || style.lineHeight
547 || (style.borderWidth && style.borderColor));
548}
549export default ZRText;