UNPKG

5.42 kBJavaScriptView Raw
1import BoundingRect from '../core/BoundingRect.js';
2import LRU from '../core/LRU.js';
3import { DEFAULT_FONT, platformApi } from '../core/platform.js';
4var textWidthCache = {};
5export function getWidth(text, font) {
6 font = font || DEFAULT_FONT;
7 var cacheOfFont = textWidthCache[font];
8 if (!cacheOfFont) {
9 cacheOfFont = textWidthCache[font] = new LRU(500);
10 }
11 var width = cacheOfFont.get(text);
12 if (width == null) {
13 width = platformApi.measureText(text, font).width;
14 cacheOfFont.put(text, width);
15 }
16 return width;
17}
18export function innerGetBoundingRect(text, font, textAlign, textBaseline) {
19 var width = getWidth(text, font);
20 var height = getLineHeight(font);
21 var x = adjustTextX(0, width, textAlign);
22 var y = adjustTextY(0, height, textBaseline);
23 var rect = new BoundingRect(x, y, width, height);
24 return rect;
25}
26export function getBoundingRect(text, font, textAlign, textBaseline) {
27 var textLines = ((text || '') + '').split('\n');
28 var len = textLines.length;
29 if (len === 1) {
30 return innerGetBoundingRect(textLines[0], font, textAlign, textBaseline);
31 }
32 else {
33 var uniondRect = new BoundingRect(0, 0, 0, 0);
34 for (var i = 0; i < textLines.length; i++) {
35 var rect = innerGetBoundingRect(textLines[i], font, textAlign, textBaseline);
36 i === 0 ? uniondRect.copy(rect) : uniondRect.union(rect);
37 }
38 return uniondRect;
39 }
40}
41export function adjustTextX(x, width, textAlign) {
42 if (textAlign === 'right') {
43 x -= width;
44 }
45 else if (textAlign === 'center') {
46 x -= width / 2;
47 }
48 return x;
49}
50export function adjustTextY(y, height, verticalAlign) {
51 if (verticalAlign === 'middle') {
52 y -= height / 2;
53 }
54 else if (verticalAlign === 'bottom') {
55 y -= height;
56 }
57 return y;
58}
59export function getLineHeight(font) {
60 return getWidth('国', font);
61}
62export function measureText(text, font) {
63 return platformApi.measureText(text, font);
64}
65export function parsePercent(value, maxValue) {
66 if (typeof value === 'string') {
67 if (value.lastIndexOf('%') >= 0) {
68 return parseFloat(value) / 100 * maxValue;
69 }
70 return parseFloat(value);
71 }
72 return value;
73}
74export function calculateTextPosition(out, opts, rect) {
75 var textPosition = opts.position || 'inside';
76 var distance = opts.distance != null ? opts.distance : 5;
77 var height = rect.height;
78 var width = rect.width;
79 var halfHeight = height / 2;
80 var x = rect.x;
81 var y = rect.y;
82 var textAlign = 'left';
83 var textVerticalAlign = 'top';
84 if (textPosition instanceof Array) {
85 x += parsePercent(textPosition[0], rect.width);
86 y += parsePercent(textPosition[1], rect.height);
87 textAlign = null;
88 textVerticalAlign = null;
89 }
90 else {
91 switch (textPosition) {
92 case 'left':
93 x -= distance;
94 y += halfHeight;
95 textAlign = 'right';
96 textVerticalAlign = 'middle';
97 break;
98 case 'right':
99 x += distance + width;
100 y += halfHeight;
101 textVerticalAlign = 'middle';
102 break;
103 case 'top':
104 x += width / 2;
105 y -= distance;
106 textAlign = 'center';
107 textVerticalAlign = 'bottom';
108 break;
109 case 'bottom':
110 x += width / 2;
111 y += height + distance;
112 textAlign = 'center';
113 break;
114 case 'inside':
115 x += width / 2;
116 y += halfHeight;
117 textAlign = 'center';
118 textVerticalAlign = 'middle';
119 break;
120 case 'insideLeft':
121 x += distance;
122 y += halfHeight;
123 textVerticalAlign = 'middle';
124 break;
125 case 'insideRight':
126 x += width - distance;
127 y += halfHeight;
128 textAlign = 'right';
129 textVerticalAlign = 'middle';
130 break;
131 case 'insideTop':
132 x += width / 2;
133 y += distance;
134 textAlign = 'center';
135 break;
136 case 'insideBottom':
137 x += width / 2;
138 y += height - distance;
139 textAlign = 'center';
140 textVerticalAlign = 'bottom';
141 break;
142 case 'insideTopLeft':
143 x += distance;
144 y += distance;
145 break;
146 case 'insideTopRight':
147 x += width - distance;
148 y += distance;
149 textAlign = 'right';
150 break;
151 case 'insideBottomLeft':
152 x += distance;
153 y += height - distance;
154 textVerticalAlign = 'bottom';
155 break;
156 case 'insideBottomRight':
157 x += width - distance;
158 y += height - distance;
159 textAlign = 'right';
160 textVerticalAlign = 'bottom';
161 break;
162 }
163 }
164 out = out || {};
165 out.x = x;
166 out.y = y;
167 out.align = textAlign;
168 out.verticalAlign = textVerticalAlign;
169 return out;
170}