text.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. import BoundingRect from '../core/BoundingRect.js';
  2. import LRU from '../core/LRU.js';
  3. import { DEFAULT_FONT, platformApi } from '../core/platform.js';
  4. var textWidthCache = {};
  5. export 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. }
  18. export 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. }
  26. export 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. }
  41. export 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. }
  50. export 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. }
  59. export function getLineHeight(font) {
  60. return getWidth('国', font);
  61. }
  62. export function measureText(text, font) {
  63. return platformApi.measureText(text, font);
  64. }
  65. export 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. }
  74. export 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. }