1 | "use strict";
|
---|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
---|
3 | exports.TextPath = void 0;
|
---|
4 | const Util_1 = require("../Util");
|
---|
5 | const Factory_1 = require("../Factory");
|
---|
6 | const Shape_1 = require("../Shape");
|
---|
7 | const Path_1 = require("./Path");
|
---|
8 | const Text_1 = require("./Text");
|
---|
9 | const Validators_1 = require("../Validators");
|
---|
10 | const Global_1 = require("../Global");
|
---|
11 | var EMPTY_STRING = '', NORMAL = 'normal';
|
---|
12 | function _fillFunc(context) {
|
---|
13 | context.fillText(this.partialText, 0, 0);
|
---|
14 | }
|
---|
15 | function _strokeFunc(context) {
|
---|
16 | context.strokeText(this.partialText, 0, 0);
|
---|
17 | }
|
---|
18 | class TextPath extends Shape_1.Shape {
|
---|
19 | constructor(config) {
|
---|
20 | super(config);
|
---|
21 | this.dummyCanvas = Util_1.Util.createCanvasElement();
|
---|
22 | this.dataArray = [];
|
---|
23 | this._readDataAttribute();
|
---|
24 | this.on('dataChange.konva', function () {
|
---|
25 | this._readDataAttribute();
|
---|
26 | this._setTextData();
|
---|
27 | });
|
---|
28 | this.on('textChange.konva alignChange.konva letterSpacingChange.konva kerningFuncChange.konva fontSizeChange.konva fontFamilyChange.konva', this._setTextData);
|
---|
29 | this._setTextData();
|
---|
30 | }
|
---|
31 | _getTextPathLength() {
|
---|
32 | return Path_1.Path.getPathLength(this.dataArray);
|
---|
33 | }
|
---|
34 | _getPointAtLength(length) {
|
---|
35 | if (!this.attrs.data) {
|
---|
36 | return null;
|
---|
37 | }
|
---|
38 | const totalLength = this.pathLength;
|
---|
39 | if (length - 1 > totalLength) {
|
---|
40 | return null;
|
---|
41 | }
|
---|
42 | return Path_1.Path.getPointAtLengthOfDataArray(length, this.dataArray);
|
---|
43 | }
|
---|
44 | _readDataAttribute() {
|
---|
45 | this.dataArray = Path_1.Path.parsePathData(this.attrs.data);
|
---|
46 | this.pathLength = this._getTextPathLength();
|
---|
47 | }
|
---|
48 | _sceneFunc(context) {
|
---|
49 | context.setAttr('font', this._getContextFont());
|
---|
50 | context.setAttr('textBaseline', this.textBaseline());
|
---|
51 | context.setAttr('textAlign', 'left');
|
---|
52 | context.save();
|
---|
53 | var textDecoration = this.textDecoration();
|
---|
54 | var fill = this.fill();
|
---|
55 | var fontSize = this.fontSize();
|
---|
56 | var glyphInfo = this.glyphInfo;
|
---|
57 | if (textDecoration === 'underline') {
|
---|
58 | context.beginPath();
|
---|
59 | }
|
---|
60 | for (var i = 0; i < glyphInfo.length; i++) {
|
---|
61 | context.save();
|
---|
62 | var p0 = glyphInfo[i].p0;
|
---|
63 | context.translate(p0.x, p0.y);
|
---|
64 | context.rotate(glyphInfo[i].rotation);
|
---|
65 | this.partialText = glyphInfo[i].text;
|
---|
66 | context.fillStrokeShape(this);
|
---|
67 | if (textDecoration === 'underline') {
|
---|
68 | if (i === 0) {
|
---|
69 | context.moveTo(0, fontSize / 2 + 1);
|
---|
70 | }
|
---|
71 | context.lineTo(fontSize, fontSize / 2 + 1);
|
---|
72 | }
|
---|
73 | context.restore();
|
---|
74 | }
|
---|
75 | if (textDecoration === 'underline') {
|
---|
76 | context.strokeStyle = fill;
|
---|
77 | context.lineWidth = fontSize / 20;
|
---|
78 | context.stroke();
|
---|
79 | }
|
---|
80 | context.restore();
|
---|
81 | }
|
---|
82 | _hitFunc(context) {
|
---|
83 | context.beginPath();
|
---|
84 | var glyphInfo = this.glyphInfo;
|
---|
85 | if (glyphInfo.length >= 1) {
|
---|
86 | var p0 = glyphInfo[0].p0;
|
---|
87 | context.moveTo(p0.x, p0.y);
|
---|
88 | }
|
---|
89 | for (var i = 0; i < glyphInfo.length; i++) {
|
---|
90 | var p1 = glyphInfo[i].p1;
|
---|
91 | context.lineTo(p1.x, p1.y);
|
---|
92 | }
|
---|
93 | context.setAttr('lineWidth', this.fontSize());
|
---|
94 | context.setAttr('strokeStyle', this.colorKey);
|
---|
95 | context.stroke();
|
---|
96 | }
|
---|
97 | getTextWidth() {
|
---|
98 | return this.textWidth;
|
---|
99 | }
|
---|
100 | getTextHeight() {
|
---|
101 | Util_1.Util.warn('text.getTextHeight() method is deprecated. Use text.height() - for full height and text.fontSize() - for one line height.');
|
---|
102 | return this.textHeight;
|
---|
103 | }
|
---|
104 | setText(text) {
|
---|
105 | return Text_1.Text.prototype.setText.call(this, text);
|
---|
106 | }
|
---|
107 | _getContextFont() {
|
---|
108 | return Text_1.Text.prototype._getContextFont.call(this);
|
---|
109 | }
|
---|
110 | _getTextSize(text) {
|
---|
111 | var dummyCanvas = this.dummyCanvas;
|
---|
112 | var _context = dummyCanvas.getContext('2d');
|
---|
113 | _context.save();
|
---|
114 | _context.font = this._getContextFont();
|
---|
115 | var metrics = _context.measureText(text);
|
---|
116 | _context.restore();
|
---|
117 | return {
|
---|
118 | width: metrics.width,
|
---|
119 | height: parseInt(`${this.fontSize()}`, 10),
|
---|
120 | };
|
---|
121 | }
|
---|
122 | _setTextData() {
|
---|
123 | const { width, height } = this._getTextSize(this.attrs.text);
|
---|
124 | this.textWidth = width;
|
---|
125 | this.textHeight = height;
|
---|
126 | this.glyphInfo = [];
|
---|
127 | if (!this.attrs.data) {
|
---|
128 | return null;
|
---|
129 | }
|
---|
130 | const letterSpacing = this.letterSpacing();
|
---|
131 | const align = this.align();
|
---|
132 | const kerningFunc = this.kerningFunc();
|
---|
133 | const textWidth = Math.max(this.textWidth + ((this.attrs.text || '').length - 1) * letterSpacing, 0);
|
---|
134 | let offset = 0;
|
---|
135 | if (align === 'center') {
|
---|
136 | offset = Math.max(0, this.pathLength / 2 - textWidth / 2);
|
---|
137 | }
|
---|
138 | if (align === 'right') {
|
---|
139 | offset = Math.max(0, this.pathLength - textWidth);
|
---|
140 | }
|
---|
141 | const charArr = (0, Text_1.stringToArray)(this.text());
|
---|
142 | let offsetToGlyph = offset;
|
---|
143 | for (var i = 0; i < charArr.length; i++) {
|
---|
144 | const charStartPoint = this._getPointAtLength(offsetToGlyph);
|
---|
145 | if (!charStartPoint)
|
---|
146 | return;
|
---|
147 | let glyphWidth = this._getTextSize(charArr[i]).width + letterSpacing;
|
---|
148 | if (charArr[i] === ' ' && align === 'justify') {
|
---|
149 | const numberOfSpaces = this.text().split(' ').length - 1;
|
---|
150 | glyphWidth += (this.pathLength - textWidth) / numberOfSpaces;
|
---|
151 | }
|
---|
152 | const charEndPoint = this._getPointAtLength(offsetToGlyph + glyphWidth);
|
---|
153 | if (!charEndPoint)
|
---|
154 | return;
|
---|
155 | const width = Path_1.Path.getLineLength(charStartPoint.x, charStartPoint.y, charEndPoint.x, charEndPoint.y);
|
---|
156 | let kern = 0;
|
---|
157 | if (kerningFunc) {
|
---|
158 | try {
|
---|
159 | kern = kerningFunc(charArr[i - 1], charArr[i]) * this.fontSize();
|
---|
160 | }
|
---|
161 | catch (e) {
|
---|
162 | kern = 0;
|
---|
163 | }
|
---|
164 | }
|
---|
165 | charStartPoint.x += kern;
|
---|
166 | charEndPoint.x += kern;
|
---|
167 | this.textWidth += kern;
|
---|
168 | const midpoint = Path_1.Path.getPointOnLine(kern + width / 2.0, charStartPoint.x, charStartPoint.y, charEndPoint.x, charEndPoint.y);
|
---|
169 | const rotation = Math.atan2(charEndPoint.y - charStartPoint.y, charEndPoint.x - charStartPoint.x);
|
---|
170 | this.glyphInfo.push({
|
---|
171 | transposeX: midpoint.x,
|
---|
172 | transposeY: midpoint.y,
|
---|
173 | text: charArr[i],
|
---|
174 | rotation: rotation,
|
---|
175 | p0: charStartPoint,
|
---|
176 | p1: charEndPoint,
|
---|
177 | });
|
---|
178 | offsetToGlyph += glyphWidth;
|
---|
179 | }
|
---|
180 | }
|
---|
181 | getSelfRect() {
|
---|
182 | if (!this.glyphInfo.length) {
|
---|
183 | return {
|
---|
184 | x: 0,
|
---|
185 | y: 0,
|
---|
186 | width: 0,
|
---|
187 | height: 0,
|
---|
188 | };
|
---|
189 | }
|
---|
190 | var points = [];
|
---|
191 | this.glyphInfo.forEach(function (info) {
|
---|
192 | points.push(info.p0.x);
|
---|
193 | points.push(info.p0.y);
|
---|
194 | points.push(info.p1.x);
|
---|
195 | points.push(info.p1.y);
|
---|
196 | });
|
---|
197 | var minX = points[0] || 0;
|
---|
198 | var maxX = points[0] || 0;
|
---|
199 | var minY = points[1] || 0;
|
---|
200 | var maxY = points[1] || 0;
|
---|
201 | var x, y;
|
---|
202 | for (var i = 0; i < points.length / 2; i++) {
|
---|
203 | x = points[i * 2];
|
---|
204 | y = points[i * 2 + 1];
|
---|
205 | minX = Math.min(minX, x);
|
---|
206 | maxX = Math.max(maxX, x);
|
---|
207 | minY = Math.min(minY, y);
|
---|
208 | maxY = Math.max(maxY, y);
|
---|
209 | }
|
---|
210 | var fontSize = this.fontSize();
|
---|
211 | return {
|
---|
212 | x: minX - fontSize / 2,
|
---|
213 | y: minY - fontSize / 2,
|
---|
214 | width: maxX - minX + fontSize,
|
---|
215 | height: maxY - minY + fontSize,
|
---|
216 | };
|
---|
217 | }
|
---|
218 | destroy() {
|
---|
219 | Util_1.Util.releaseCanvas(this.dummyCanvas);
|
---|
220 | return super.destroy();
|
---|
221 | }
|
---|
222 | }
|
---|
223 | exports.TextPath = TextPath;
|
---|
224 | TextPath.prototype._fillFunc = _fillFunc;
|
---|
225 | TextPath.prototype._strokeFunc = _strokeFunc;
|
---|
226 | TextPath.prototype._fillFuncHit = _fillFunc;
|
---|
227 | TextPath.prototype._strokeFuncHit = _strokeFunc;
|
---|
228 | TextPath.prototype.className = 'TextPath';
|
---|
229 | TextPath.prototype._attrsAffectingSize = ['text', 'fontSize', 'data'];
|
---|
230 | (0, Global_1._registerNode)(TextPath);
|
---|
231 | Factory_1.Factory.addGetterSetter(TextPath, 'data');
|
---|
232 | Factory_1.Factory.addGetterSetter(TextPath, 'fontFamily', 'Arial');
|
---|
233 | Factory_1.Factory.addGetterSetter(TextPath, 'fontSize', 12, (0, Validators_1.getNumberValidator)());
|
---|
234 | Factory_1.Factory.addGetterSetter(TextPath, 'fontStyle', NORMAL);
|
---|
235 | Factory_1.Factory.addGetterSetter(TextPath, 'align', 'left');
|
---|
236 | Factory_1.Factory.addGetterSetter(TextPath, 'letterSpacing', 0, (0, Validators_1.getNumberValidator)());
|
---|
237 | Factory_1.Factory.addGetterSetter(TextPath, 'textBaseline', 'middle');
|
---|
238 | Factory_1.Factory.addGetterSetter(TextPath, 'fontVariant', NORMAL);
|
---|
239 | Factory_1.Factory.addGetterSetter(TextPath, 'text', EMPTY_STRING);
|
---|
240 | Factory_1.Factory.addGetterSetter(TextPath, 'textDecoration', null);
|
---|
241 | Factory_1.Factory.addGetterSetter(TextPath, 'kerningFunc', null);
|
---|