text.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. define(function(require, exports, module) {
  2. var TextContent = require('./textcontent');
  3. var ShapeContainer = require('./shapecontainer');
  4. var svg = require('./svg');
  5. var utils = require('../core/utils');
  6. var offsetHash = {};
  7. function getTextBoundOffset(text) {
  8. var font = text._cachedFontHash;
  9. if (offsetHash[font]) {
  10. return offsetHash[font];
  11. }
  12. var textContent = text.getContent();
  13. text.setContent('百度Fex');
  14. var bbox = text.getBoundaryBox(),
  15. y = text.getY();
  16. if (!bbox.height) return {
  17. top: 0,
  18. bottom: 0,
  19. middle: 0
  20. };
  21. var topOffset = y - bbox.y + (+text.node.getAttribute('dy')),
  22. bottomOffset = topOffset - bbox.height;
  23. text.setContent(textContent);
  24. return (offsetHash[font] = {
  25. top: topOffset,
  26. bottom: bottomOffset,
  27. middle: (topOffset + bottomOffset) / 2
  28. });
  29. }
  30. return require('../core/class').createClass('Text', {
  31. base: TextContent,
  32. mixins: [ShapeContainer],
  33. constructor: function(content) {
  34. this.callBase('text');
  35. if (content !== undefined) {
  36. this.setContent(content);
  37. }
  38. this._buildFontHash();
  39. },
  40. fixPosition: function() {
  41. if (!this.__fixedPosition) {
  42. this.setVerticalAlign(this.getVerticalAlign());
  43. }
  44. },
  45. _buildFontHash: function() {
  46. var style = window.getComputedStyle(this.node);
  47. this._cachedFontHash = [style.fontFamily,
  48. style.fontSize,
  49. style.fontStretch,
  50. style.fontStyle,
  51. style.fontVariant,
  52. style.fontWeight
  53. ].join('-');
  54. },
  55. _fontChanged: function(font) {
  56. var last = this._lastFont;
  57. var current = utils.extend({}, last, font);
  58. if (!last) {
  59. this._lastFont = font;
  60. return true;
  61. }
  62. var changed = last.family != current.family ||
  63. last.size != current.size ||
  64. last.style != current.style ||
  65. last.weight != current.weight;
  66. this._lastFont = current;
  67. return changed;
  68. },
  69. setX: function(x) {
  70. this.node.setAttribute('x', x);
  71. return this;
  72. },
  73. setPosition: function(x, y) {
  74. return this.setX(x).setY(y);
  75. },
  76. setY: function(y) {
  77. this.node.setAttribute('y', y);
  78. return this;
  79. },
  80. getX: function() {
  81. return +this.node.getAttribute('x') || 0;
  82. },
  83. getY: function() {
  84. return +this.node.getAttribute('y') || 0;
  85. },
  86. setFont: function(font) {
  87. this.callBase(font);
  88. if (this._fontChanged(font)) {
  89. this._buildFontHash();
  90. this.setVerticalAlign(this.getVerticalAlign());
  91. }
  92. return this;
  93. },
  94. setTextAnchor: function(anchor) {
  95. this.node.setAttribute('text-anchor', anchor);
  96. return this;
  97. },
  98. getTextAnchor: function() {
  99. return this.node.getAttribute('text-anchor') || 'start';
  100. },
  101. // top/bottom/middle/baseline
  102. setVerticalAlign: function(align) {
  103. this.whenPaperReady(function() {
  104. var dy;
  105. switch (align) {
  106. case 'top':
  107. dy = getTextBoundOffset(this).top;
  108. break;
  109. case 'bottom':
  110. dy = getTextBoundOffset(this).bottom;
  111. break;
  112. case 'middle':
  113. dy = getTextBoundOffset(this).middle;
  114. break;
  115. default:
  116. dy = 0;
  117. }
  118. if (dy) this.__fixedPosition = true;
  119. this.node.setAttribute('dy', dy);
  120. });
  121. this.verticalAlign = align;
  122. return this;
  123. },
  124. getVerticalAlign: function() {
  125. return this.verticalAlign || 'baseline';
  126. },
  127. setStartOffset: function(offset) {
  128. // only for text path
  129. if (this.shapeNode != this.node) {
  130. this.shapeNode.setAttribute('startOffset', offset * 100 + '%');
  131. }
  132. },
  133. addSpan: function(span) {
  134. this.addShape(span);
  135. return this;
  136. },
  137. setPath: function(path) {
  138. var textpath = this.shapeNode;
  139. if (this.shapeNode == this.node) {
  140. // 当前还不是 textpath
  141. textpath = this.shapeNode = svg.createNode('textPath');
  142. while (this.node.firstChild) {
  143. this.shapeNode.appendChild(this.node.firstChild);
  144. }
  145. this.node.appendChild(textpath);
  146. }
  147. textpath.setAttributeNS(svg.xlink, 'xlink:href', '#' + path.node.id);
  148. this.setTextAnchor(this.getTextAnchor());
  149. return this;
  150. }
  151. });
  152. });