HTextElement.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. import {
  2. extendPrototype,
  3. } from '../../utils/functionExtensions';
  4. import {
  5. createSizedArray,
  6. } from '../../utils/helpers/arrays';
  7. import createNS from '../../utils/helpers/svg_elements';
  8. import createTag from '../../utils/helpers/html_elements';
  9. import BaseElement from '../BaseElement';
  10. import TransformElement from '../helpers/TransformElement';
  11. import HierarchyElement from '../helpers/HierarchyElement';
  12. import FrameElement from '../helpers/FrameElement';
  13. import RenderableDOMElement from '../helpers/RenderableDOMElement';
  14. import ITextElement from '../TextElement';
  15. import HBaseElement from './HBaseElement';
  16. import {
  17. lineCapEnum,
  18. lineJoinEnum,
  19. } from '../../utils/helpers/shapeEnums';
  20. import {
  21. styleDiv,
  22. } from '../../utils/common';
  23. function HTextElement(data, globalData, comp) {
  24. this.textSpans = [];
  25. this.textPaths = [];
  26. this.currentBBox = {
  27. x: 999999,
  28. y: -999999,
  29. h: 0,
  30. w: 0,
  31. };
  32. this.renderType = 'svg';
  33. this.isMasked = false;
  34. this.initElement(data, globalData, comp);
  35. }
  36. extendPrototype([BaseElement, TransformElement, HBaseElement, HierarchyElement, FrameElement, RenderableDOMElement, ITextElement], HTextElement);
  37. HTextElement.prototype.createContent = function () {
  38. this.isMasked = this.checkMasks();
  39. if (this.isMasked) {
  40. this.renderType = 'svg';
  41. this.compW = this.comp.data.w;
  42. this.compH = this.comp.data.h;
  43. this.svgElement.setAttribute('width', this.compW);
  44. this.svgElement.setAttribute('height', this.compH);
  45. var g = createNS('g');
  46. this.maskedElement.appendChild(g);
  47. this.innerElem = g;
  48. } else {
  49. this.renderType = 'html';
  50. this.innerElem = this.layerElement;
  51. }
  52. this.checkParenting();
  53. };
  54. HTextElement.prototype.buildNewText = function () {
  55. var documentData = this.textProperty.currentData;
  56. this.renderedLetters = createSizedArray(documentData.l ? documentData.l.length : 0);
  57. var innerElemStyle = this.innerElem.style;
  58. var textColor = documentData.fc ? this.buildColor(documentData.fc) : 'rgba(0,0,0,0)';
  59. innerElemStyle.fill = textColor;
  60. innerElemStyle.color = textColor;
  61. if (documentData.sc) {
  62. innerElemStyle.stroke = this.buildColor(documentData.sc);
  63. innerElemStyle.strokeWidth = documentData.sw + 'px';
  64. }
  65. var fontData = this.globalData.fontManager.getFontByName(documentData.f);
  66. if (!this.globalData.fontManager.chars) {
  67. innerElemStyle.fontSize = documentData.finalSize + 'px';
  68. innerElemStyle.lineHeight = documentData.finalSize + 'px';
  69. if (fontData.fClass) {
  70. this.innerElem.className = fontData.fClass;
  71. } else {
  72. innerElemStyle.fontFamily = fontData.fFamily;
  73. var fWeight = documentData.fWeight;
  74. var fStyle = documentData.fStyle;
  75. innerElemStyle.fontStyle = fStyle;
  76. innerElemStyle.fontWeight = fWeight;
  77. }
  78. }
  79. var i;
  80. var len;
  81. var letters = documentData.l;
  82. len = letters.length;
  83. var tSpan;
  84. var tParent;
  85. var tCont;
  86. var matrixHelper = this.mHelper;
  87. var shapes;
  88. var shapeStr = '';
  89. var cnt = 0;
  90. for (i = 0; i < len; i += 1) {
  91. if (this.globalData.fontManager.chars) {
  92. if (!this.textPaths[cnt]) {
  93. tSpan = createNS('path');
  94. tSpan.setAttribute('stroke-linecap', lineCapEnum[1]);
  95. tSpan.setAttribute('stroke-linejoin', lineJoinEnum[2]);
  96. tSpan.setAttribute('stroke-miterlimit', '4');
  97. } else {
  98. tSpan = this.textPaths[cnt];
  99. }
  100. if (!this.isMasked) {
  101. if (this.textSpans[cnt]) {
  102. tParent = this.textSpans[cnt];
  103. tCont = tParent.children[0];
  104. } else {
  105. tParent = createTag('div');
  106. tParent.style.lineHeight = 0;
  107. tCont = createNS('svg');
  108. tCont.appendChild(tSpan);
  109. styleDiv(tParent);
  110. }
  111. }
  112. } else if (!this.isMasked) {
  113. if (this.textSpans[cnt]) {
  114. tParent = this.textSpans[cnt];
  115. tSpan = this.textPaths[cnt];
  116. } else {
  117. tParent = createTag('span');
  118. styleDiv(tParent);
  119. tSpan = createTag('span');
  120. styleDiv(tSpan);
  121. tParent.appendChild(tSpan);
  122. }
  123. } else {
  124. tSpan = this.textPaths[cnt] ? this.textPaths[cnt] : createNS('text');
  125. }
  126. // tSpan.setAttribute('visibility', 'hidden');
  127. if (this.globalData.fontManager.chars) {
  128. var charData = this.globalData.fontManager.getCharData(documentData.finalText[i], fontData.fStyle, this.globalData.fontManager.getFontByName(documentData.f).fFamily);
  129. var shapeData;
  130. if (charData) {
  131. shapeData = charData.data;
  132. } else {
  133. shapeData = null;
  134. }
  135. matrixHelper.reset();
  136. if (shapeData && shapeData.shapes && shapeData.shapes.length) {
  137. shapes = shapeData.shapes[0].it;
  138. matrixHelper.scale(documentData.finalSize / 100, documentData.finalSize / 100);
  139. shapeStr = this.createPathShape(matrixHelper, shapes);
  140. tSpan.setAttribute('d', shapeStr);
  141. }
  142. if (!this.isMasked) {
  143. this.innerElem.appendChild(tParent);
  144. if (shapeData && shapeData.shapes) {
  145. // document.body.appendChild is needed to get exact measure of shape
  146. document.body.appendChild(tCont);
  147. var boundingBox = tCont.getBBox();
  148. tCont.setAttribute('width', boundingBox.width + 2);
  149. tCont.setAttribute('height', boundingBox.height + 2);
  150. tCont.setAttribute('viewBox', (boundingBox.x - 1) + ' ' + (boundingBox.y - 1) + ' ' + (boundingBox.width + 2) + ' ' + (boundingBox.height + 2));
  151. var tContStyle = tCont.style;
  152. var tContTranslation = 'translate(' + (boundingBox.x - 1) + 'px,' + (boundingBox.y - 1) + 'px)';
  153. tContStyle.transform = tContTranslation;
  154. tContStyle.webkitTransform = tContTranslation;
  155. letters[i].yOffset = boundingBox.y - 1;
  156. } else {
  157. tCont.setAttribute('width', 1);
  158. tCont.setAttribute('height', 1);
  159. }
  160. tParent.appendChild(tCont);
  161. } else {
  162. this.innerElem.appendChild(tSpan);
  163. }
  164. } else {
  165. tSpan.textContent = letters[i].val;
  166. tSpan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve');
  167. if (!this.isMasked) {
  168. this.innerElem.appendChild(tParent);
  169. //
  170. var tStyle = tSpan.style;
  171. var tSpanTranslation = 'translate3d(0,' + -documentData.finalSize / 1.2 + 'px,0)';
  172. tStyle.transform = tSpanTranslation;
  173. tStyle.webkitTransform = tSpanTranslation;
  174. } else {
  175. this.innerElem.appendChild(tSpan);
  176. }
  177. }
  178. //
  179. if (!this.isMasked) {
  180. this.textSpans[cnt] = tParent;
  181. } else {
  182. this.textSpans[cnt] = tSpan;
  183. }
  184. this.textSpans[cnt].style.display = 'block';
  185. this.textPaths[cnt] = tSpan;
  186. cnt += 1;
  187. }
  188. while (cnt < this.textSpans.length) {
  189. this.textSpans[cnt].style.display = 'none';
  190. cnt += 1;
  191. }
  192. };
  193. HTextElement.prototype.renderInnerContent = function () {
  194. this.validateText();
  195. var svgStyle;
  196. if (this.data.singleShape) {
  197. if (!this._isFirstFrame && !this.lettersChangedFlag) {
  198. return;
  199. } if (this.isMasked && this.finalTransform._matMdf) {
  200. // Todo Benchmark if using this is better than getBBox
  201. this.svgElement.setAttribute('viewBox', -this.finalTransform.mProp.p.v[0] + ' ' + -this.finalTransform.mProp.p.v[1] + ' ' + this.compW + ' ' + this.compH);
  202. svgStyle = this.svgElement.style;
  203. var translation = 'translate(' + -this.finalTransform.mProp.p.v[0] + 'px,' + -this.finalTransform.mProp.p.v[1] + 'px)';
  204. svgStyle.transform = translation;
  205. svgStyle.webkitTransform = translation;
  206. }
  207. }
  208. this.textAnimator.getMeasures(this.textProperty.currentData, this.lettersChangedFlag);
  209. if (!this.lettersChangedFlag && !this.textAnimator.lettersChangedFlag) {
  210. return;
  211. }
  212. var i;
  213. var len;
  214. var count = 0;
  215. var renderedLetters = this.textAnimator.renderedLetters;
  216. var letters = this.textProperty.currentData.l;
  217. len = letters.length;
  218. var renderedLetter;
  219. var textSpan;
  220. var textPath;
  221. for (i = 0; i < len; i += 1) {
  222. if (letters[i].n) {
  223. count += 1;
  224. } else {
  225. textSpan = this.textSpans[i];
  226. textPath = this.textPaths[i];
  227. renderedLetter = renderedLetters[count];
  228. count += 1;
  229. if (renderedLetter._mdf.m) {
  230. if (!this.isMasked) {
  231. textSpan.style.webkitTransform = renderedLetter.m;
  232. textSpan.style.transform = renderedLetter.m;
  233. } else {
  234. textSpan.setAttribute('transform', renderedLetter.m);
  235. }
  236. }
  237. /// /textSpan.setAttribute('opacity',renderedLetter.o);
  238. textSpan.style.opacity = renderedLetter.o;
  239. if (renderedLetter.sw && renderedLetter._mdf.sw) {
  240. textPath.setAttribute('stroke-width', renderedLetter.sw);
  241. }
  242. if (renderedLetter.sc && renderedLetter._mdf.sc) {
  243. textPath.setAttribute('stroke', renderedLetter.sc);
  244. }
  245. if (renderedLetter.fc && renderedLetter._mdf.fc) {
  246. textPath.setAttribute('fill', renderedLetter.fc);
  247. textPath.style.color = renderedLetter.fc;
  248. }
  249. }
  250. }
  251. if (this.innerElem.getBBox && !this.hidden && (this._isFirstFrame || this._mdf)) {
  252. var boundingBox = this.innerElem.getBBox();
  253. if (this.currentBBox.w !== boundingBox.width) {
  254. this.currentBBox.w = boundingBox.width;
  255. this.svgElement.setAttribute('width', boundingBox.width);
  256. }
  257. if (this.currentBBox.h !== boundingBox.height) {
  258. this.currentBBox.h = boundingBox.height;
  259. this.svgElement.setAttribute('height', boundingBox.height);
  260. }
  261. var margin = 1;
  262. if (this.currentBBox.w !== (boundingBox.width + margin * 2) || this.currentBBox.h !== (boundingBox.height + margin * 2) || this.currentBBox.x !== (boundingBox.x - margin) || this.currentBBox.y !== (boundingBox.y - margin)) {
  263. this.currentBBox.w = boundingBox.width + margin * 2;
  264. this.currentBBox.h = boundingBox.height + margin * 2;
  265. this.currentBBox.x = boundingBox.x - margin;
  266. this.currentBBox.y = boundingBox.y - margin;
  267. this.svgElement.setAttribute('viewBox', this.currentBBox.x + ' ' + this.currentBBox.y + ' ' + this.currentBBox.w + ' ' + this.currentBBox.h);
  268. svgStyle = this.svgElement.style;
  269. var svgTransform = 'translate(' + this.currentBBox.x + 'px,' + this.currentBBox.y + 'px)';
  270. svgStyle.transform = svgTransform;
  271. svgStyle.webkitTransform = svgTransform;
  272. }
  273. }
  274. };
  275. export default HTextElement;