@nasser-sw/fabric 7.0.1-beta3 → 7.0.1-beta4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/0 +0 -0
- package/dist/index.js +323 -155
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/index.min.mjs +1 -1
- package/dist/index.min.mjs.map +1 -1
- package/dist/index.mjs +323 -155
- package/dist/index.mjs.map +1 -1
- package/dist/index.node.cjs +323 -155
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.mjs +323 -155
- package/dist/index.node.mjs.map +1 -1
- package/dist/package.json.min.mjs +1 -1
- package/dist/package.json.mjs +1 -1
- package/dist/src/shapes/Line.d.ts +31 -86
- package/dist/src/shapes/Line.d.ts.map +1 -1
- package/dist/src/shapes/Line.min.mjs +1 -1
- package/dist/src/shapes/Line.min.mjs.map +1 -1
- package/dist/src/shapes/Line.mjs +323 -154
- package/dist/src/shapes/Line.mjs.map +1 -1
- package/dist-extensions/src/shapes/CustomLine.d.ts +10 -0
- package/dist-extensions/src/shapes/CustomLine.d.ts.map +1 -0
- package/dist-extensions/src/shapes/Line.d.ts +31 -86
- package/dist-extensions/src/shapes/Line.d.ts.map +1 -1
- package/fabric-test-editor.html +157 -8
- package/fabric-test2.html +513 -0
- package/fabric.ts +182 -182
- package/package.json +1 -1
- package/src/shapes/Line.ts +372 -158
- package/debug/konva/CHANGELOG.md +0 -1474
- package/debug/konva/LICENSE +0 -22
- package/debug/konva/README.md +0 -205
- package/debug/konva/gulpfile.mjs +0 -110
- package/debug/konva/package.json +0 -139
- package/debug/konva/release.sh +0 -65
- package/debug/konva/resources/doc-includes/ContainerParams.txt +0 -6
- package/debug/konva/resources/doc-includes/NodeParams.txt +0 -20
- package/debug/konva/resources/doc-includes/ShapeParams.txt +0 -53
- package/debug/konva/resources/jsdoc.conf.json +0 -28
- package/debug/konva/rollup.config.mjs +0 -32
- package/debug/konva/src/Animation.ts +0 -237
- package/debug/konva/src/BezierFunctions.ts +0 -826
- package/debug/konva/src/Canvas.ts +0 -193
- package/debug/konva/src/Container.ts +0 -649
- package/debug/konva/src/Context.ts +0 -1017
- package/debug/konva/src/Core.ts +0 -5
- package/debug/konva/src/DragAndDrop.ts +0 -173
- package/debug/konva/src/Factory.ts +0 -246
- package/debug/konva/src/FastLayer.ts +0 -29
- package/debug/konva/src/Global.ts +0 -210
- package/debug/konva/src/Group.ts +0 -31
- package/debug/konva/src/Layer.ts +0 -546
- package/debug/konva/src/Node.ts +0 -3477
- package/debug/konva/src/PointerEvents.ts +0 -67
- package/debug/konva/src/Shape.ts +0 -2081
- package/debug/konva/src/Stage.ts +0 -1000
- package/debug/konva/src/Tween.ts +0 -811
- package/debug/konva/src/Util.ts +0 -1123
- package/debug/konva/src/Validators.ts +0 -210
- package/debug/konva/src/_CoreInternals.ts +0 -85
- package/debug/konva/src/_FullInternals.ts +0 -171
- package/debug/konva/src/canvas-backend.ts +0 -36
- package/debug/konva/src/filters/Blur.ts +0 -388
- package/debug/konva/src/filters/Brighten.ts +0 -48
- package/debug/konva/src/filters/Brightness.ts +0 -30
- package/debug/konva/src/filters/Contrast.ts +0 -75
- package/debug/konva/src/filters/Emboss.ts +0 -207
- package/debug/konva/src/filters/Enhance.ts +0 -154
- package/debug/konva/src/filters/Grayscale.ts +0 -25
- package/debug/konva/src/filters/HSL.ts +0 -108
- package/debug/konva/src/filters/HSV.ts +0 -106
- package/debug/konva/src/filters/Invert.ts +0 -23
- package/debug/konva/src/filters/Kaleidoscope.ts +0 -274
- package/debug/konva/src/filters/Mask.ts +0 -220
- package/debug/konva/src/filters/Noise.ts +0 -44
- package/debug/konva/src/filters/Pixelate.ts +0 -107
- package/debug/konva/src/filters/Posterize.ts +0 -46
- package/debug/konva/src/filters/RGB.ts +0 -82
- package/debug/konva/src/filters/RGBA.ts +0 -103
- package/debug/konva/src/filters/Sepia.ts +0 -27
- package/debug/konva/src/filters/Solarize.ts +0 -29
- package/debug/konva/src/filters/Threshold.ts +0 -44
- package/debug/konva/src/index.ts +0 -3
- package/debug/konva/src/shapes/Arc.ts +0 -176
- package/debug/konva/src/shapes/Arrow.ts +0 -231
- package/debug/konva/src/shapes/Circle.ts +0 -76
- package/debug/konva/src/shapes/Ellipse.ts +0 -121
- package/debug/konva/src/shapes/Image.ts +0 -319
- package/debug/konva/src/shapes/Label.ts +0 -386
- package/debug/konva/src/shapes/Line.ts +0 -364
- package/debug/konva/src/shapes/Path.ts +0 -1013
- package/debug/konva/src/shapes/Rect.ts +0 -79
- package/debug/konva/src/shapes/RegularPolygon.ts +0 -167
- package/debug/konva/src/shapes/Ring.ts +0 -94
- package/debug/konva/src/shapes/Sprite.ts +0 -370
- package/debug/konva/src/shapes/Star.ts +0 -125
- package/debug/konva/src/shapes/Text.ts +0 -1065
- package/debug/konva/src/shapes/TextPath.ts +0 -583
- package/debug/konva/src/shapes/Transformer.ts +0 -1889
- package/debug/konva/src/shapes/Wedge.ts +0 -129
- package/debug/konva/src/skia-backend.ts +0 -35
- package/debug/konva/src/types.ts +0 -84
- package/debug/konva/tsconfig.json +0 -31
- package/debug/konva/tsconfig.test.json +0 -7
|
@@ -1,1065 +0,0 @@
|
|
|
1
|
-
import { Util } from '../Util.ts';
|
|
2
|
-
import type { Context } from '../Context.ts';
|
|
3
|
-
import { Factory } from '../Factory.ts';
|
|
4
|
-
import type { ShapeConfig } from '../Shape.ts';
|
|
5
|
-
import { Shape } from '../Shape.ts';
|
|
6
|
-
import { Konva } from '../Global.ts';
|
|
7
|
-
import {
|
|
8
|
-
getNumberValidator,
|
|
9
|
-
getStringValidator,
|
|
10
|
-
getNumberOrAutoValidator,
|
|
11
|
-
getBooleanValidator,
|
|
12
|
-
} from '../Validators.ts';
|
|
13
|
-
import { _registerNode } from '../Global.ts';
|
|
14
|
-
|
|
15
|
-
import type { GetSet } from '../types.ts';
|
|
16
|
-
|
|
17
|
-
export interface CharRenderProps {
|
|
18
|
-
char: string;
|
|
19
|
-
index: number;
|
|
20
|
-
x: number;
|
|
21
|
-
y: number;
|
|
22
|
-
lineIndex: number;
|
|
23
|
-
column: number;
|
|
24
|
-
isLastInLine: boolean;
|
|
25
|
-
width: number;
|
|
26
|
-
context: Context;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function stringToArray(string: string): string[] {
|
|
30
|
-
// Use Unicode-aware splitting
|
|
31
|
-
return [...string].reduce((acc, char, index, array) => {
|
|
32
|
-
// Handle emoji with skin tone modifiers and ZWJ sequences
|
|
33
|
-
if (/\p{Emoji}/u.test(char)) {
|
|
34
|
-
// Check if next character is a modifier or ZWJ sequence
|
|
35
|
-
const nextChar = array[index + 1];
|
|
36
|
-
if (nextChar && /\p{Emoji_Modifier}|\u200D/u.test(nextChar)) {
|
|
37
|
-
// If we have a modifier, combine with current emoji
|
|
38
|
-
acc.push(char + nextChar);
|
|
39
|
-
// Skip the next character since we've used it
|
|
40
|
-
array[index + 1] = '';
|
|
41
|
-
} else {
|
|
42
|
-
// No modifier - treat as separate emoji
|
|
43
|
-
acc.push(char);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
// Handle regional indicator symbols (flags)
|
|
47
|
-
else if (
|
|
48
|
-
/\p{Regional_Indicator}{2}/u.test(char + (array[index + 1] || ''))
|
|
49
|
-
) {
|
|
50
|
-
acc.push(char + array[index + 1]);
|
|
51
|
-
}
|
|
52
|
-
// Handle Indic scripts and other combining characters
|
|
53
|
-
else if (index > 0 && /\p{Mn}|\p{Me}|\p{Mc}/u.test(char)) {
|
|
54
|
-
acc[acc.length - 1] += char;
|
|
55
|
-
}
|
|
56
|
-
// Handle other characters
|
|
57
|
-
else if (char) {
|
|
58
|
-
// Only push if not an empty string (skipped modifier)
|
|
59
|
-
acc.push(char);
|
|
60
|
-
}
|
|
61
|
-
return acc;
|
|
62
|
-
}, [] as string[]);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export interface TextConfig extends ShapeConfig {
|
|
66
|
-
direction?: string;
|
|
67
|
-
text?: string;
|
|
68
|
-
fontFamily?: string;
|
|
69
|
-
fontSize?: number;
|
|
70
|
-
fontStyle?: string;
|
|
71
|
-
fontVariant?: string;
|
|
72
|
-
textDecoration?: string;
|
|
73
|
-
align?: string;
|
|
74
|
-
verticalAlign?: string;
|
|
75
|
-
padding?: number;
|
|
76
|
-
lineHeight?: number;
|
|
77
|
-
letterSpacing?: number;
|
|
78
|
-
wrap?: string;
|
|
79
|
-
ellipsis?: boolean;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// constants
|
|
83
|
-
const AUTO = 'auto',
|
|
84
|
-
//CANVAS = 'canvas',
|
|
85
|
-
CENTER = 'center',
|
|
86
|
-
INHERIT = 'inherit',
|
|
87
|
-
JUSTIFY = 'justify',
|
|
88
|
-
CHANGE_KONVA = 'Change.konva',
|
|
89
|
-
CONTEXT_2D = '2d',
|
|
90
|
-
DASH = '-',
|
|
91
|
-
LEFT = 'left',
|
|
92
|
-
TEXT = 'text',
|
|
93
|
-
TEXT_UPPER = 'Text',
|
|
94
|
-
TOP = 'top',
|
|
95
|
-
BOTTOM = 'bottom',
|
|
96
|
-
MIDDLE = 'middle',
|
|
97
|
-
NORMAL = 'normal',
|
|
98
|
-
PX_SPACE = 'px ',
|
|
99
|
-
SPACE = ' ',
|
|
100
|
-
RIGHT = 'right',
|
|
101
|
-
RTL = 'rtl',
|
|
102
|
-
WORD = 'word',
|
|
103
|
-
CHAR = 'char',
|
|
104
|
-
NONE = 'none',
|
|
105
|
-
ELLIPSIS = '…',
|
|
106
|
-
ATTR_CHANGE_LIST = [
|
|
107
|
-
'direction',
|
|
108
|
-
'fontFamily',
|
|
109
|
-
'fontSize',
|
|
110
|
-
'fontStyle',
|
|
111
|
-
'fontVariant',
|
|
112
|
-
'padding',
|
|
113
|
-
'align',
|
|
114
|
-
'verticalAlign',
|
|
115
|
-
'lineHeight',
|
|
116
|
-
'text',
|
|
117
|
-
'width',
|
|
118
|
-
'height',
|
|
119
|
-
'wrap',
|
|
120
|
-
'ellipsis',
|
|
121
|
-
'letterSpacing',
|
|
122
|
-
],
|
|
123
|
-
// cached variables
|
|
124
|
-
attrChangeListLen = ATTR_CHANGE_LIST.length;
|
|
125
|
-
|
|
126
|
-
function normalizeFontFamily(fontFamily: string) {
|
|
127
|
-
return fontFamily
|
|
128
|
-
.split(',')
|
|
129
|
-
.map((family) => {
|
|
130
|
-
family = family.trim();
|
|
131
|
-
const hasSpace = family.indexOf(' ') >= 0;
|
|
132
|
-
const hasQuotes = family.indexOf('"') >= 0 || family.indexOf("'") >= 0;
|
|
133
|
-
if (hasSpace && !hasQuotes) {
|
|
134
|
-
family = `"${family}"`;
|
|
135
|
-
}
|
|
136
|
-
return family;
|
|
137
|
-
})
|
|
138
|
-
.join(', ');
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
let dummyContext: CanvasRenderingContext2D;
|
|
142
|
-
function getDummyContext() {
|
|
143
|
-
if (dummyContext) {
|
|
144
|
-
return dummyContext;
|
|
145
|
-
}
|
|
146
|
-
dummyContext = Util.createCanvasElement().getContext(
|
|
147
|
-
CONTEXT_2D
|
|
148
|
-
) as CanvasRenderingContext2D;
|
|
149
|
-
return dummyContext;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
function _fillFunc(this: Text, context: Context) {
|
|
153
|
-
context.fillText(this._partialText, this._partialTextX, this._partialTextY);
|
|
154
|
-
}
|
|
155
|
-
function _strokeFunc(this: Text, context: Context) {
|
|
156
|
-
context.setAttr('miterLimit', 2);
|
|
157
|
-
context.strokeText(this._partialText, this._partialTextX, this._partialTextY);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
function checkDefaultFill(config?: TextConfig) {
|
|
161
|
-
config = config || {};
|
|
162
|
-
|
|
163
|
-
// set default color to black
|
|
164
|
-
if (
|
|
165
|
-
!config.fillLinearGradientColorStops &&
|
|
166
|
-
!config.fillRadialGradientColorStops &&
|
|
167
|
-
!config.fillPatternImage
|
|
168
|
-
) {
|
|
169
|
-
config.fill = config.fill || 'black';
|
|
170
|
-
}
|
|
171
|
-
return config;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* Text constructor
|
|
176
|
-
* @constructor
|
|
177
|
-
* @memberof Konva
|
|
178
|
-
* @augments Konva.Shape
|
|
179
|
-
* @param {Object} config
|
|
180
|
-
* @param {String} [config.direction] default is inherit
|
|
181
|
-
* @param {String} [config.fontFamily] default is Arial
|
|
182
|
-
* @param {Number} [config.fontSize] in pixels. Default is 12
|
|
183
|
-
* @param {String} [config.fontStyle] can be 'normal', 'italic', or 'bold', '500' or even 'italic bold'. 'normal' is the default.
|
|
184
|
-
* @param {String} [config.fontVariant] can be normal or small-caps. Default is normal
|
|
185
|
-
* @param {String} [config.textDecoration] can be line-through, underline or empty string. Default is empty string.
|
|
186
|
-
* @param {String} config.text
|
|
187
|
-
* @param {String} [config.align] can be left, center, right or justify
|
|
188
|
-
* @param {String} [config.verticalAlign] can be top, middle or bottom
|
|
189
|
-
* @param {Number} [config.padding]
|
|
190
|
-
* @param {Number} [config.lineHeight] default is 1
|
|
191
|
-
* @param {String} [config.wrap] can be "word", "char", or "none". Default is word
|
|
192
|
-
* @param {Boolean} [config.ellipsis] can be true or false. Default is false. if Konva.Text config is set to wrap="none" and ellipsis=true, then it will add "..." to the end
|
|
193
|
-
* @@shapeParams
|
|
194
|
-
* @@nodeParams
|
|
195
|
-
* @example
|
|
196
|
-
* var text = new Konva.Text({
|
|
197
|
-
* x: 10,
|
|
198
|
-
* y: 15,
|
|
199
|
-
* text: 'Simple Text',
|
|
200
|
-
* fontSize: 30,
|
|
201
|
-
* fontFamily: 'Calibri',
|
|
202
|
-
* fill: 'green'
|
|
203
|
-
* });
|
|
204
|
-
*/
|
|
205
|
-
export class Text extends Shape<TextConfig> {
|
|
206
|
-
textArr: Array<{ text: string; width: number; lastInParagraph: boolean }>;
|
|
207
|
-
_partialText: string;
|
|
208
|
-
_partialTextX = 0;
|
|
209
|
-
_partialTextY = 0;
|
|
210
|
-
|
|
211
|
-
textWidth: number;
|
|
212
|
-
textHeight: number;
|
|
213
|
-
constructor(config?: TextConfig) {
|
|
214
|
-
super(checkDefaultFill(config));
|
|
215
|
-
// update text data for certain attr changes
|
|
216
|
-
for (let n = 0; n < attrChangeListLen; n++) {
|
|
217
|
-
this.on(ATTR_CHANGE_LIST[n] + CHANGE_KONVA, this._setTextData);
|
|
218
|
-
}
|
|
219
|
-
this._setTextData();
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
_sceneFunc(context: Context) {
|
|
223
|
-
const textArr = this.textArr,
|
|
224
|
-
textArrLen = textArr.length;
|
|
225
|
-
|
|
226
|
-
if (!this.text()) {
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
let padding = this.padding(),
|
|
231
|
-
fontSize = this.fontSize(),
|
|
232
|
-
lineHeightPx = this.lineHeight() * fontSize,
|
|
233
|
-
verticalAlign = this.verticalAlign(),
|
|
234
|
-
direction = this.direction(),
|
|
235
|
-
alignY = 0,
|
|
236
|
-
align = this.align(),
|
|
237
|
-
totalWidth = this.getWidth(),
|
|
238
|
-
letterSpacing = this.letterSpacing(),
|
|
239
|
-
charRenderFunc = this.charRenderFunc(),
|
|
240
|
-
fill = this.fill(),
|
|
241
|
-
textDecoration = this.textDecoration(),
|
|
242
|
-
shouldUnderline = textDecoration.indexOf('underline') !== -1,
|
|
243
|
-
shouldLineThrough = textDecoration.indexOf('line-through') !== -1,
|
|
244
|
-
n;
|
|
245
|
-
|
|
246
|
-
direction = direction === INHERIT ? context.direction : direction;
|
|
247
|
-
|
|
248
|
-
let translateY = lineHeightPx / 2;
|
|
249
|
-
let baseline = MIDDLE;
|
|
250
|
-
if (!Konva.legacyTextRendering) {
|
|
251
|
-
const metrics = this.measureSize('M'); // Use a sample character to get the ascent
|
|
252
|
-
|
|
253
|
-
baseline = 'alphabetic';
|
|
254
|
-
const ascent =
|
|
255
|
-
metrics.fontBoundingBoxAscent ?? metrics.actualBoundingBoxAscent;
|
|
256
|
-
const descent =
|
|
257
|
-
metrics.fontBoundingBoxDescent ?? metrics.actualBoundingBoxDescent;
|
|
258
|
-
|
|
259
|
-
translateY = (ascent - descent) / 2 + lineHeightPx / 2;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
if (direction === RTL) {
|
|
263
|
-
context.setAttr('direction', direction);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
context.setAttr('font', this._getContextFont());
|
|
267
|
-
|
|
268
|
-
context.setAttr('textBaseline', baseline);
|
|
269
|
-
|
|
270
|
-
context.setAttr('textAlign', LEFT);
|
|
271
|
-
|
|
272
|
-
// handle vertical alignment
|
|
273
|
-
if (verticalAlign === MIDDLE) {
|
|
274
|
-
alignY = (this.getHeight() - textArrLen * lineHeightPx - padding * 2) / 2;
|
|
275
|
-
} else if (verticalAlign === BOTTOM) {
|
|
276
|
-
alignY = this.getHeight() - textArrLen * lineHeightPx - padding * 2;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
context.translate(padding, alignY + padding);
|
|
280
|
-
|
|
281
|
-
// draw text lines
|
|
282
|
-
for (n = 0; n < textArrLen; n++) {
|
|
283
|
-
let lineTranslateX = 0;
|
|
284
|
-
let lineTranslateY = 0;
|
|
285
|
-
const obj = textArr[n],
|
|
286
|
-
text = obj.text,
|
|
287
|
-
width = obj.width,
|
|
288
|
-
lastLine = obj.lastInParagraph;
|
|
289
|
-
|
|
290
|
-
// horizontal alignment
|
|
291
|
-
context.save();
|
|
292
|
-
if (align === RIGHT) {
|
|
293
|
-
lineTranslateX += totalWidth - width - padding * 2;
|
|
294
|
-
} else if (align === CENTER) {
|
|
295
|
-
lineTranslateX += (totalWidth - width - padding * 2) / 2;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
if (shouldUnderline) {
|
|
299
|
-
context.save();
|
|
300
|
-
context.beginPath();
|
|
301
|
-
|
|
302
|
-
const yOffset = !Konva.legacyTextRendering
|
|
303
|
-
? Math.round(fontSize / 4)
|
|
304
|
-
: Math.round(fontSize / 2);
|
|
305
|
-
const x = lineTranslateX;
|
|
306
|
-
const y = translateY + lineTranslateY + yOffset;
|
|
307
|
-
context.moveTo(x, y);
|
|
308
|
-
const lineWidth =
|
|
309
|
-
align === JUSTIFY && !lastLine ? totalWidth - padding * 2 : width;
|
|
310
|
-
context.lineTo(x + Math.round(lineWidth), y);
|
|
311
|
-
|
|
312
|
-
// I have no idea what is real ratio
|
|
313
|
-
// just /15 looks good enough
|
|
314
|
-
context.lineWidth = fontSize / 15;
|
|
315
|
-
|
|
316
|
-
const gradient = this._getLinearGradient();
|
|
317
|
-
context.strokeStyle = gradient || fill;
|
|
318
|
-
context.stroke();
|
|
319
|
-
context.restore();
|
|
320
|
-
}
|
|
321
|
-
// draw line-through above the text content
|
|
322
|
-
|
|
323
|
-
// As `letterSpacing` isn't supported on Safari, we use this polyfill.
|
|
324
|
-
// The exception is for RTL text, which we rely on native as it cannot
|
|
325
|
-
// be supported otherwise.
|
|
326
|
-
if (
|
|
327
|
-
direction !== RTL &&
|
|
328
|
-
(letterSpacing !== 0 || align === JUSTIFY || charRenderFunc)
|
|
329
|
-
) {
|
|
330
|
-
// var words = text.split(' ');
|
|
331
|
-
const spacesNumber = text.split(' ').length - 1;
|
|
332
|
-
const array = stringToArray(text);
|
|
333
|
-
for (let li = 0; li < array.length; li++) {
|
|
334
|
-
const letter = array[li];
|
|
335
|
-
// skip justify for the last line
|
|
336
|
-
if (letter === ' ' && !lastLine && align === JUSTIFY) {
|
|
337
|
-
lineTranslateX += (totalWidth - padding * 2 - width) / spacesNumber;
|
|
338
|
-
// context.translate(
|
|
339
|
-
// Math.floor((totalWidth - padding * 2 - width) / spacesNumber),
|
|
340
|
-
// 0
|
|
341
|
-
// );
|
|
342
|
-
}
|
|
343
|
-
this._partialTextX = lineTranslateX;
|
|
344
|
-
this._partialTextY = translateY + lineTranslateY;
|
|
345
|
-
this._partialText = letter;
|
|
346
|
-
|
|
347
|
-
if (charRenderFunc) {
|
|
348
|
-
context.save();
|
|
349
|
-
const previousLines = textArr.slice(0, n);
|
|
350
|
-
const previousGraphemes = previousLines.reduce(
|
|
351
|
-
(acc, line) => acc + stringToArray(line.text).length,
|
|
352
|
-
0
|
|
353
|
-
);
|
|
354
|
-
const charIndex = li + previousGraphemes;
|
|
355
|
-
charRenderFunc({
|
|
356
|
-
char: letter,
|
|
357
|
-
index: charIndex,
|
|
358
|
-
x: lineTranslateX,
|
|
359
|
-
y: translateY + lineTranslateY,
|
|
360
|
-
lineIndex: n,
|
|
361
|
-
column: li,
|
|
362
|
-
isLastInLine: lastLine,
|
|
363
|
-
width: this.measureSize(letter).width,
|
|
364
|
-
context,
|
|
365
|
-
});
|
|
366
|
-
}
|
|
367
|
-
context.fillStrokeShape(this);
|
|
368
|
-
if (charRenderFunc) {
|
|
369
|
-
context.restore();
|
|
370
|
-
}
|
|
371
|
-
lineTranslateX += this.measureSize(letter).width + letterSpacing;
|
|
372
|
-
}
|
|
373
|
-
} else {
|
|
374
|
-
if (letterSpacing !== 0) {
|
|
375
|
-
context.setAttr('letterSpacing', `${letterSpacing}px`);
|
|
376
|
-
}
|
|
377
|
-
this._partialTextX = lineTranslateX;
|
|
378
|
-
this._partialTextY = translateY + lineTranslateY;
|
|
379
|
-
this._partialText = text;
|
|
380
|
-
|
|
381
|
-
context.fillStrokeShape(this);
|
|
382
|
-
}
|
|
383
|
-
// draw line-through above the text content
|
|
384
|
-
if (shouldLineThrough) {
|
|
385
|
-
context.save();
|
|
386
|
-
context.beginPath();
|
|
387
|
-
const yOffset = !Konva.legacyTextRendering
|
|
388
|
-
? -Math.round(fontSize / 4)
|
|
389
|
-
: 0;
|
|
390
|
-
context.moveTo(0, translateY + lineTranslateY + yOffset);
|
|
391
|
-
const lineWidth =
|
|
392
|
-
align === JUSTIFY && !lastLine ? totalWidth - padding * 2 : width;
|
|
393
|
-
context.lineTo(
|
|
394
|
-
Math.round(lineWidth),
|
|
395
|
-
translateY + lineTranslateY + yOffset
|
|
396
|
-
);
|
|
397
|
-
context.lineWidth = fontSize / 15;
|
|
398
|
-
const gradient = this._getLinearGradient();
|
|
399
|
-
context.strokeStyle = gradient || fill;
|
|
400
|
-
context.stroke();
|
|
401
|
-
context.restore();
|
|
402
|
-
}
|
|
403
|
-
context.restore();
|
|
404
|
-
if (textArrLen > 1) {
|
|
405
|
-
translateY += lineHeightPx;
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
_hitFunc(context: Context) {
|
|
410
|
-
const width = this.getWidth(),
|
|
411
|
-
height = this.getHeight();
|
|
412
|
-
|
|
413
|
-
context.beginPath();
|
|
414
|
-
context.rect(0, 0, width, height);
|
|
415
|
-
context.closePath();
|
|
416
|
-
context.fillStrokeShape(this);
|
|
417
|
-
}
|
|
418
|
-
setText(text: string) {
|
|
419
|
-
const str = Util._isString(text)
|
|
420
|
-
? text
|
|
421
|
-
: text === null || text === undefined
|
|
422
|
-
? ''
|
|
423
|
-
: text + '';
|
|
424
|
-
this._setAttr(TEXT, str);
|
|
425
|
-
return this;
|
|
426
|
-
}
|
|
427
|
-
getWidth() {
|
|
428
|
-
const isAuto = this.attrs.width === AUTO || this.attrs.width === undefined;
|
|
429
|
-
return isAuto ? this.getTextWidth() + this.padding() * 2 : this.attrs.width;
|
|
430
|
-
}
|
|
431
|
-
getHeight() {
|
|
432
|
-
const isAuto =
|
|
433
|
-
this.attrs.height === AUTO || this.attrs.height === undefined;
|
|
434
|
-
return isAuto
|
|
435
|
-
? this.fontSize() * this.textArr.length * this.lineHeight() +
|
|
436
|
-
this.padding() * 2
|
|
437
|
-
: this.attrs.height;
|
|
438
|
-
}
|
|
439
|
-
/**
|
|
440
|
-
* get pure text width without padding
|
|
441
|
-
* @method
|
|
442
|
-
* @name Konva.Text#getTextWidth
|
|
443
|
-
* @returns {Number}
|
|
444
|
-
*/
|
|
445
|
-
getTextWidth() {
|
|
446
|
-
return this.textWidth;
|
|
447
|
-
}
|
|
448
|
-
getTextHeight() {
|
|
449
|
-
Util.warn(
|
|
450
|
-
'text.getTextHeight() method is deprecated. Use text.height() - for full height and text.fontSize() - for one line height.'
|
|
451
|
-
);
|
|
452
|
-
return this.textHeight;
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
/**
|
|
456
|
-
* measure string with the font of current text shape.
|
|
457
|
-
* That method can't handle multiline text.
|
|
458
|
-
* @method
|
|
459
|
-
* @name Konva.Text#measureSize
|
|
460
|
-
* @param {String} text text to measure
|
|
461
|
-
* @returns {Object} { width , height } of measured text
|
|
462
|
-
*/
|
|
463
|
-
measureSize(text: string) {
|
|
464
|
-
let _context = getDummyContext(),
|
|
465
|
-
fontSize = this.fontSize(),
|
|
466
|
-
metrics: TextMetrics;
|
|
467
|
-
|
|
468
|
-
_context.save();
|
|
469
|
-
_context.font = this._getContextFont();
|
|
470
|
-
|
|
471
|
-
metrics = _context.measureText(text);
|
|
472
|
-
_context.restore();
|
|
473
|
-
|
|
474
|
-
// Scale the fallback values based on the provided fontSize compared to the sample size (100 in your new case)
|
|
475
|
-
const scaleFactor = fontSize / 100;
|
|
476
|
-
|
|
477
|
-
// Note, fallback values are from chrome browser with 100px font size and font-family "Arial"
|
|
478
|
-
return {
|
|
479
|
-
actualBoundingBoxAscent:
|
|
480
|
-
metrics.actualBoundingBoxAscent ?? 71.58203125 * scaleFactor,
|
|
481
|
-
actualBoundingBoxDescent: metrics.actualBoundingBoxDescent ?? 0, // Remains zero as there is no descent in the provided metrics
|
|
482
|
-
actualBoundingBoxLeft:
|
|
483
|
-
metrics.actualBoundingBoxLeft ?? -7.421875 * scaleFactor,
|
|
484
|
-
actualBoundingBoxRight:
|
|
485
|
-
metrics.actualBoundingBoxRight ?? 75.732421875 * scaleFactor,
|
|
486
|
-
alphabeticBaseline: metrics.alphabeticBaseline ?? 0, // Remains zero as it's typically relative to the baseline itself
|
|
487
|
-
emHeightAscent: metrics.emHeightAscent ?? 100 * scaleFactor,
|
|
488
|
-
emHeightDescent: metrics.emHeightDescent ?? -20 * scaleFactor,
|
|
489
|
-
fontBoundingBoxAscent: metrics.fontBoundingBoxAscent ?? 91 * scaleFactor,
|
|
490
|
-
fontBoundingBoxDescent:
|
|
491
|
-
metrics.fontBoundingBoxDescent ?? 21 * scaleFactor,
|
|
492
|
-
hangingBaseline:
|
|
493
|
-
metrics.hangingBaseline ?? 72.80000305175781 * scaleFactor,
|
|
494
|
-
ideographicBaseline: metrics.ideographicBaseline ?? -21 * scaleFactor,
|
|
495
|
-
width: metrics.width,
|
|
496
|
-
height: fontSize, // Typically set to the font size
|
|
497
|
-
};
|
|
498
|
-
}
|
|
499
|
-
_getContextFont() {
|
|
500
|
-
return (
|
|
501
|
-
this.fontStyle() +
|
|
502
|
-
SPACE +
|
|
503
|
-
this.fontVariant() +
|
|
504
|
-
SPACE +
|
|
505
|
-
(this.fontSize() + PX_SPACE) +
|
|
506
|
-
// wrap font family into " so font families with spaces works ok
|
|
507
|
-
normalizeFontFamily(this.fontFamily())
|
|
508
|
-
);
|
|
509
|
-
}
|
|
510
|
-
_addTextLine(line: string) {
|
|
511
|
-
const align = this.align();
|
|
512
|
-
if (align === JUSTIFY) {
|
|
513
|
-
line = line.trim();
|
|
514
|
-
}
|
|
515
|
-
const width = this._getTextWidth(line);
|
|
516
|
-
return this.textArr.push({
|
|
517
|
-
text: line,
|
|
518
|
-
width: width,
|
|
519
|
-
lastInParagraph: false,
|
|
520
|
-
});
|
|
521
|
-
}
|
|
522
|
-
_getTextWidth(text: string) {
|
|
523
|
-
const letterSpacing = this.letterSpacing();
|
|
524
|
-
const length = text.length;
|
|
525
|
-
// letterSpacing * length is the total letter spacing for the text
|
|
526
|
-
// previously we used letterSpacing * (length - 1) but it doesn't match DOM behavior
|
|
527
|
-
return getDummyContext().measureText(text).width + letterSpacing * length;
|
|
528
|
-
}
|
|
529
|
-
_setTextData() {
|
|
530
|
-
let lines = this.text().split('\n'),
|
|
531
|
-
fontSize = +this.fontSize(),
|
|
532
|
-
textWidth = 0,
|
|
533
|
-
lineHeightPx = this.lineHeight() * fontSize,
|
|
534
|
-
width = this.attrs.width,
|
|
535
|
-
height = this.attrs.height,
|
|
536
|
-
fixedWidth = width !== AUTO && width !== undefined,
|
|
537
|
-
fixedHeight = height !== AUTO && height !== undefined,
|
|
538
|
-
padding = this.padding(),
|
|
539
|
-
maxWidth = width - padding * 2,
|
|
540
|
-
maxHeightPx = height - padding * 2,
|
|
541
|
-
currentHeightPx = 0,
|
|
542
|
-
wrap = this.wrap(),
|
|
543
|
-
// align = this.align(),
|
|
544
|
-
shouldWrap = wrap !== NONE,
|
|
545
|
-
wrapAtWord = wrap !== CHAR && shouldWrap,
|
|
546
|
-
shouldAddEllipsis = this.ellipsis();
|
|
547
|
-
|
|
548
|
-
this.textArr = [];
|
|
549
|
-
getDummyContext().font = this._getContextFont();
|
|
550
|
-
const additionalWidth = shouldAddEllipsis
|
|
551
|
-
? this._getTextWidth(ELLIPSIS)
|
|
552
|
-
: 0;
|
|
553
|
-
for (let i = 0, max = lines.length; i < max; ++i) {
|
|
554
|
-
let line = lines[i];
|
|
555
|
-
|
|
556
|
-
let lineWidth = this._getTextWidth(line);
|
|
557
|
-
if (fixedWidth && lineWidth > maxWidth) {
|
|
558
|
-
/*
|
|
559
|
-
* if width is fixed and line does not fit entirely
|
|
560
|
-
* break the line into multiple fitting lines
|
|
561
|
-
*/
|
|
562
|
-
while (line.length > 0) {
|
|
563
|
-
/*
|
|
564
|
-
* use binary search to find the longest substring that
|
|
565
|
-
* that would fit in the specified width
|
|
566
|
-
*/
|
|
567
|
-
let low = 0,
|
|
568
|
-
high = stringToArray(line).length, // Convert to array for proper emoji handling
|
|
569
|
-
match = '',
|
|
570
|
-
matchWidth = 0;
|
|
571
|
-
while (low < high) {
|
|
572
|
-
const mid = (low + high) >>> 1,
|
|
573
|
-
// Convert array indices to string
|
|
574
|
-
lineArray = stringToArray(line),
|
|
575
|
-
substr = lineArray.slice(0, mid + 1).join(''),
|
|
576
|
-
substrWidth = this._getTextWidth(substr);
|
|
577
|
-
|
|
578
|
-
// Only add ellipsis width when we need to consider truncation
|
|
579
|
-
// for the current line (when it might be the last visible line)
|
|
580
|
-
const shouldConsiderEllipsis =
|
|
581
|
-
shouldAddEllipsis &&
|
|
582
|
-
fixedHeight &&
|
|
583
|
-
currentHeightPx + lineHeightPx > maxHeightPx;
|
|
584
|
-
|
|
585
|
-
const effectiveWidth = shouldConsiderEllipsis
|
|
586
|
-
? substrWidth + additionalWidth
|
|
587
|
-
: substrWidth;
|
|
588
|
-
|
|
589
|
-
if (effectiveWidth <= maxWidth) {
|
|
590
|
-
low = mid + 1;
|
|
591
|
-
match = substr;
|
|
592
|
-
matchWidth = substrWidth; // Store actual text width without ellipsis
|
|
593
|
-
} else {
|
|
594
|
-
high = mid;
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
/*
|
|
598
|
-
* 'low' is now the index of the substring end
|
|
599
|
-
* 'match' is the substring
|
|
600
|
-
* 'matchWidth' is the substring width in px
|
|
601
|
-
*/
|
|
602
|
-
if (match) {
|
|
603
|
-
// a fitting substring was found
|
|
604
|
-
if (wrapAtWord) {
|
|
605
|
-
// try to find a space or dash where wrapping could be done
|
|
606
|
-
const lineArray = stringToArray(line);
|
|
607
|
-
const matchArray = stringToArray(match);
|
|
608
|
-
const nextChar = lineArray[matchArray.length];
|
|
609
|
-
const nextIsSpaceOrDash = nextChar === SPACE || nextChar === DASH;
|
|
610
|
-
|
|
611
|
-
let wrapIndex;
|
|
612
|
-
if (nextIsSpaceOrDash && matchWidth <= maxWidth) {
|
|
613
|
-
wrapIndex = matchArray.length;
|
|
614
|
-
} else {
|
|
615
|
-
// Find last space or dash in the array
|
|
616
|
-
const lastSpaceIndex = matchArray.lastIndexOf(SPACE);
|
|
617
|
-
const lastDashIndex = matchArray.lastIndexOf(DASH);
|
|
618
|
-
wrapIndex = Math.max(lastSpaceIndex, lastDashIndex) + 1;
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
if (wrapIndex > 0) {
|
|
622
|
-
low = wrapIndex;
|
|
623
|
-
match = lineArray.slice(0, low).join('');
|
|
624
|
-
matchWidth = this._getTextWidth(match);
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
// if (align === 'right') {
|
|
628
|
-
match = match.trimRight();
|
|
629
|
-
// }
|
|
630
|
-
this._addTextLine(match);
|
|
631
|
-
textWidth = Math.max(textWidth, matchWidth);
|
|
632
|
-
currentHeightPx += lineHeightPx;
|
|
633
|
-
|
|
634
|
-
const shouldHandleEllipsis =
|
|
635
|
-
this._shouldHandleEllipsis(currentHeightPx);
|
|
636
|
-
if (shouldHandleEllipsis) {
|
|
637
|
-
this._tryToAddEllipsisToLastLine();
|
|
638
|
-
/*
|
|
639
|
-
* stop wrapping if wrapping is disabled or if adding
|
|
640
|
-
* one more line would overflow the fixed height
|
|
641
|
-
*/
|
|
642
|
-
break;
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
// Convert remaining text using array operations
|
|
646
|
-
const lineArray = stringToArray(line);
|
|
647
|
-
line = lineArray.slice(low).join('').trimLeft();
|
|
648
|
-
|
|
649
|
-
if (line.length > 0) {
|
|
650
|
-
lineWidth = this._getTextWidth(line);
|
|
651
|
-
if (lineWidth <= maxWidth) {
|
|
652
|
-
this._addTextLine(line);
|
|
653
|
-
currentHeightPx += lineHeightPx;
|
|
654
|
-
textWidth = Math.max(textWidth, lineWidth);
|
|
655
|
-
break;
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
} else {
|
|
659
|
-
// not even one character could fit in the element, abort
|
|
660
|
-
break;
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
|
-
} else {
|
|
664
|
-
// element width is automatically adjusted to max line width
|
|
665
|
-
this._addTextLine(line);
|
|
666
|
-
currentHeightPx += lineHeightPx;
|
|
667
|
-
textWidth = Math.max(textWidth, lineWidth);
|
|
668
|
-
if (this._shouldHandleEllipsis(currentHeightPx) && i < max - 1) {
|
|
669
|
-
this._tryToAddEllipsisToLastLine();
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
// if element height is fixed, abort if adding one more line would overflow
|
|
673
|
-
if (this.textArr[this.textArr.length - 1]) {
|
|
674
|
-
this.textArr[this.textArr.length - 1].lastInParagraph = true;
|
|
675
|
-
}
|
|
676
|
-
if (fixedHeight && currentHeightPx + lineHeightPx > maxHeightPx) {
|
|
677
|
-
break;
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
this.textHeight = fontSize;
|
|
681
|
-
// var maxTextWidth = 0;
|
|
682
|
-
// for(var j = 0; j < this.textArr.length; j++) {
|
|
683
|
-
// maxTextWidth = Math.max(maxTextWidth, this.textArr[j].width);
|
|
684
|
-
// }
|
|
685
|
-
this.textWidth = textWidth;
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
/**
|
|
689
|
-
* whether to handle ellipsis, there are two cases:
|
|
690
|
-
* 1. the current line is the last line
|
|
691
|
-
* 2. wrap is NONE
|
|
692
|
-
* @param {Number} currentHeightPx
|
|
693
|
-
* @returns {Boolean}
|
|
694
|
-
*/
|
|
695
|
-
_shouldHandleEllipsis(currentHeightPx: number): boolean {
|
|
696
|
-
const fontSize = +this.fontSize(),
|
|
697
|
-
lineHeightPx = this.lineHeight() * fontSize,
|
|
698
|
-
height = this.attrs.height,
|
|
699
|
-
fixedHeight = height !== AUTO && height !== undefined,
|
|
700
|
-
padding = this.padding(),
|
|
701
|
-
maxHeightPx = height - padding * 2,
|
|
702
|
-
wrap = this.wrap(),
|
|
703
|
-
shouldWrap = wrap !== NONE;
|
|
704
|
-
|
|
705
|
-
return (
|
|
706
|
-
!shouldWrap ||
|
|
707
|
-
(fixedHeight && currentHeightPx + lineHeightPx > maxHeightPx)
|
|
708
|
-
);
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
_tryToAddEllipsisToLastLine(): void {
|
|
712
|
-
const width = this.attrs.width,
|
|
713
|
-
fixedWidth = width !== AUTO && width !== undefined,
|
|
714
|
-
padding = this.padding(),
|
|
715
|
-
maxWidth = width - padding * 2,
|
|
716
|
-
shouldAddEllipsis = this.ellipsis();
|
|
717
|
-
|
|
718
|
-
const lastLine = this.textArr[this.textArr.length - 1];
|
|
719
|
-
if (!lastLine || !shouldAddEllipsis) {
|
|
720
|
-
return;
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
if (fixedWidth) {
|
|
724
|
-
const haveSpace = this._getTextWidth(lastLine.text + ELLIPSIS) < maxWidth;
|
|
725
|
-
if (!haveSpace) {
|
|
726
|
-
lastLine.text = lastLine.text.slice(0, lastLine.text.length - 3);
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
this.textArr.splice(this.textArr.length - 1, 1);
|
|
731
|
-
this._addTextLine(lastLine.text + ELLIPSIS);
|
|
732
|
-
}
|
|
733
|
-
|
|
734
|
-
// for text we can't disable stroke scaling
|
|
735
|
-
// if we do, the result will be unexpected
|
|
736
|
-
getStrokeScaleEnabled() {
|
|
737
|
-
return true;
|
|
738
|
-
}
|
|
739
|
-
|
|
740
|
-
_useBufferCanvas() {
|
|
741
|
-
const hasLine =
|
|
742
|
-
this.textDecoration().indexOf('underline') !== -1 ||
|
|
743
|
-
this.textDecoration().indexOf('line-through') !== -1;
|
|
744
|
-
const hasShadow = this.hasShadow();
|
|
745
|
-
if (hasLine && hasShadow) {
|
|
746
|
-
return true;
|
|
747
|
-
}
|
|
748
|
-
return super._useBufferCanvas();
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
direction: GetSet<string, this>;
|
|
752
|
-
fontFamily: GetSet<string, this>;
|
|
753
|
-
fontSize: GetSet<number, this>;
|
|
754
|
-
fontStyle: GetSet<string, this>;
|
|
755
|
-
fontVariant: GetSet<string, this>;
|
|
756
|
-
align: GetSet<string, this>;
|
|
757
|
-
letterSpacing: GetSet<number, this>;
|
|
758
|
-
verticalAlign: GetSet<string, this>;
|
|
759
|
-
padding: GetSet<number, this>;
|
|
760
|
-
lineHeight: GetSet<number, this>;
|
|
761
|
-
textDecoration: GetSet<string, this>;
|
|
762
|
-
text: GetSet<string, this>;
|
|
763
|
-
wrap: GetSet<string, this>;
|
|
764
|
-
ellipsis: GetSet<boolean, this>;
|
|
765
|
-
charRenderFunc: GetSet<null | ((props: CharRenderProps) => void), this>;
|
|
766
|
-
}
|
|
767
|
-
|
|
768
|
-
Text.prototype._fillFunc = _fillFunc;
|
|
769
|
-
Text.prototype._strokeFunc = _strokeFunc;
|
|
770
|
-
Text.prototype.className = TEXT_UPPER;
|
|
771
|
-
Text.prototype._attrsAffectingSize = [
|
|
772
|
-
'text',
|
|
773
|
-
'fontSize',
|
|
774
|
-
'padding',
|
|
775
|
-
'wrap',
|
|
776
|
-
'lineHeight',
|
|
777
|
-
'letterSpacing',
|
|
778
|
-
];
|
|
779
|
-
_registerNode(Text);
|
|
780
|
-
|
|
781
|
-
/**
|
|
782
|
-
* get/set width of text area, which includes padding.
|
|
783
|
-
* @name Konva.Text#width
|
|
784
|
-
* @method
|
|
785
|
-
* @param {Number} width
|
|
786
|
-
* @returns {Number}
|
|
787
|
-
* @example
|
|
788
|
-
* // get width
|
|
789
|
-
* var width = text.width();
|
|
790
|
-
*
|
|
791
|
-
* // set width
|
|
792
|
-
* text.width(20);
|
|
793
|
-
*
|
|
794
|
-
* // set to auto
|
|
795
|
-
* text.width('auto');
|
|
796
|
-
* text.width() // will return calculated width, and not "auto"
|
|
797
|
-
*/
|
|
798
|
-
Factory.overWriteSetter(Text, 'width', getNumberOrAutoValidator());
|
|
799
|
-
|
|
800
|
-
/**
|
|
801
|
-
* get/set the height of the text area, which takes into account multi-line text, line heights, and padding.
|
|
802
|
-
* @name Konva.Text#height
|
|
803
|
-
* @method
|
|
804
|
-
* @param {Number} height
|
|
805
|
-
* @returns {Number}
|
|
806
|
-
* @example
|
|
807
|
-
* // get height
|
|
808
|
-
* var height = text.height();
|
|
809
|
-
*
|
|
810
|
-
* // set height
|
|
811
|
-
* text.height(20);
|
|
812
|
-
*
|
|
813
|
-
* // set to auto
|
|
814
|
-
* text.height('auto');
|
|
815
|
-
* text.height() // will return calculated height, and not "auto"
|
|
816
|
-
*/
|
|
817
|
-
|
|
818
|
-
Factory.overWriteSetter(Text, 'height', getNumberOrAutoValidator());
|
|
819
|
-
|
|
820
|
-
/**
|
|
821
|
-
* get/set direction
|
|
822
|
-
* @name Konva.Text#direction
|
|
823
|
-
* @method
|
|
824
|
-
* @param {String} direction
|
|
825
|
-
* @returns {String}
|
|
826
|
-
* @example
|
|
827
|
-
* // get direction
|
|
828
|
-
* var direction = text.direction();
|
|
829
|
-
*
|
|
830
|
-
* // set direction
|
|
831
|
-
* text.direction('rtl');
|
|
832
|
-
*/
|
|
833
|
-
Factory.addGetterSetter(Text, 'direction', INHERIT);
|
|
834
|
-
|
|
835
|
-
/**
|
|
836
|
-
* get/set font family
|
|
837
|
-
* @name Konva.Text#fontFamily
|
|
838
|
-
* @method
|
|
839
|
-
* @param {String} fontFamily
|
|
840
|
-
* @returns {String}
|
|
841
|
-
* @example
|
|
842
|
-
* // get font family
|
|
843
|
-
* var fontFamily = text.fontFamily();
|
|
844
|
-
*
|
|
845
|
-
* // set font family
|
|
846
|
-
* text.fontFamily('Arial');
|
|
847
|
-
*/
|
|
848
|
-
Factory.addGetterSetter(Text, 'fontFamily', 'Arial');
|
|
849
|
-
|
|
850
|
-
/**
|
|
851
|
-
* get/set font size in pixels
|
|
852
|
-
* @name Konva.Text#fontSize
|
|
853
|
-
* @method
|
|
854
|
-
* @param {Number} fontSize
|
|
855
|
-
* @returns {Number}
|
|
856
|
-
* @example
|
|
857
|
-
* // get font size
|
|
858
|
-
* var fontSize = text.fontSize();
|
|
859
|
-
*
|
|
860
|
-
* // set font size to 22px
|
|
861
|
-
* text.fontSize(22);
|
|
862
|
-
*/
|
|
863
|
-
Factory.addGetterSetter(Text, 'fontSize', 12, getNumberValidator());
|
|
864
|
-
|
|
865
|
-
/**
|
|
866
|
-
* get/set font style. Can be 'normal', 'italic', or 'bold', '500' or even 'italic bold'. 'normal' is the default.
|
|
867
|
-
* @name Konva.Text#fontStyle
|
|
868
|
-
* @method
|
|
869
|
-
* @param {String} fontStyle
|
|
870
|
-
* @returns {String}
|
|
871
|
-
* @example
|
|
872
|
-
* // get font style
|
|
873
|
-
* var fontStyle = text.fontStyle();
|
|
874
|
-
*
|
|
875
|
-
* // set font style
|
|
876
|
-
* text.fontStyle('bold');
|
|
877
|
-
*/
|
|
878
|
-
|
|
879
|
-
Factory.addGetterSetter(Text, 'fontStyle', NORMAL);
|
|
880
|
-
|
|
881
|
-
/**
|
|
882
|
-
* get/set font variant. Can be 'normal' or 'small-caps'. 'normal' is the default.
|
|
883
|
-
* @name Konva.Text#fontVariant
|
|
884
|
-
* @method
|
|
885
|
-
* @param {String} fontVariant
|
|
886
|
-
* @returns {String}
|
|
887
|
-
* @example
|
|
888
|
-
* // get font variant
|
|
889
|
-
* var fontVariant = text.fontVariant();
|
|
890
|
-
*
|
|
891
|
-
* // set font variant
|
|
892
|
-
* text.fontVariant('small-caps');
|
|
893
|
-
*/
|
|
894
|
-
|
|
895
|
-
Factory.addGetterSetter(Text, 'fontVariant', NORMAL);
|
|
896
|
-
|
|
897
|
-
/**
|
|
898
|
-
* get/set padding
|
|
899
|
-
* @name Konva.Text#padding
|
|
900
|
-
* @method
|
|
901
|
-
* @param {Number} padding
|
|
902
|
-
* @returns {Number}
|
|
903
|
-
* @example
|
|
904
|
-
* // get padding
|
|
905
|
-
* var padding = text.padding();
|
|
906
|
-
*
|
|
907
|
-
* // set padding to 10 pixels
|
|
908
|
-
* text.padding(10);
|
|
909
|
-
*/
|
|
910
|
-
|
|
911
|
-
Factory.addGetterSetter(Text, 'padding', 0, getNumberValidator());
|
|
912
|
-
|
|
913
|
-
/**
|
|
914
|
-
* get/set horizontal align of text. Can be 'left', 'center', 'right' or 'justify'
|
|
915
|
-
* @name Konva.Text#align
|
|
916
|
-
* @method
|
|
917
|
-
* @param {String} align
|
|
918
|
-
* @returns {String}
|
|
919
|
-
* @example
|
|
920
|
-
* // get text align
|
|
921
|
-
* var align = text.align();
|
|
922
|
-
*
|
|
923
|
-
* // center text
|
|
924
|
-
* text.align('center');
|
|
925
|
-
*
|
|
926
|
-
* // align text to right
|
|
927
|
-
* text.align('right');
|
|
928
|
-
*
|
|
929
|
-
* // justify text
|
|
930
|
-
*/
|
|
931
|
-
|
|
932
|
-
Factory.addGetterSetter(Text, 'align', LEFT);
|
|
933
|
-
|
|
934
|
-
/**
|
|
935
|
-
* get/set vertical align of text. Can be 'top', 'middle', 'bottom'.
|
|
936
|
-
* @name Konva.Text#verticalAlign
|
|
937
|
-
* @method
|
|
938
|
-
* @param {String} verticalAlign
|
|
939
|
-
* @returns {String}
|
|
940
|
-
* @example
|
|
941
|
-
* // get text vertical align
|
|
942
|
-
* var verticalAlign = text.verticalAlign();
|
|
943
|
-
*
|
|
944
|
-
* // center text
|
|
945
|
-
* text.verticalAlign('middle');
|
|
946
|
-
*/
|
|
947
|
-
|
|
948
|
-
Factory.addGetterSetter(Text, 'verticalAlign', TOP);
|
|
949
|
-
|
|
950
|
-
/**
|
|
951
|
-
* get/set line height. The default is 1.
|
|
952
|
-
* @name Konva.Text#lineHeight
|
|
953
|
-
* @method
|
|
954
|
-
* @param {Number} lineHeight
|
|
955
|
-
* @returns {Number}
|
|
956
|
-
* @example
|
|
957
|
-
* // get line height
|
|
958
|
-
* var lineHeight = text.lineHeight();
|
|
959
|
-
*
|
|
960
|
-
* // set the line height
|
|
961
|
-
* text.lineHeight(2);
|
|
962
|
-
*/
|
|
963
|
-
|
|
964
|
-
Factory.addGetterSetter(Text, 'lineHeight', 1, getNumberValidator());
|
|
965
|
-
|
|
966
|
-
/**
|
|
967
|
-
* get/set wrap. Can be "word", "char", or "none". Default is "word".
|
|
968
|
-
* In "word" wrapping any word still can be wrapped if it can't be placed in the required width
|
|
969
|
-
* without breaks.
|
|
970
|
-
* @name Konva.Text#wrap
|
|
971
|
-
* @method
|
|
972
|
-
* @param {String} wrap
|
|
973
|
-
* @returns {String}
|
|
974
|
-
* @example
|
|
975
|
-
* // get wrap
|
|
976
|
-
* var wrap = text.wrap();
|
|
977
|
-
*
|
|
978
|
-
* // set wrap
|
|
979
|
-
* text.wrap('word');
|
|
980
|
-
*/
|
|
981
|
-
|
|
982
|
-
Factory.addGetterSetter(Text, 'wrap', WORD);
|
|
983
|
-
|
|
984
|
-
/**
|
|
985
|
-
* get/set ellipsis. Can be true or false. Default is false. If ellipses is true,
|
|
986
|
-
* Konva will add "..." at the end of the text if it doesn't have enough space to write characters.
|
|
987
|
-
* That is possible only when you limit both width and height of the text
|
|
988
|
-
* @name Konva.Text#ellipsis
|
|
989
|
-
* @method
|
|
990
|
-
* @param {Boolean} ellipsis
|
|
991
|
-
* @returns {Boolean}
|
|
992
|
-
* @example
|
|
993
|
-
* // get ellipsis param, returns true or false
|
|
994
|
-
* var ellipsis = text.ellipsis();
|
|
995
|
-
*
|
|
996
|
-
* // set ellipsis
|
|
997
|
-
* text.ellipsis(true);
|
|
998
|
-
*/
|
|
999
|
-
|
|
1000
|
-
Factory.addGetterSetter(Text, 'ellipsis', false, getBooleanValidator());
|
|
1001
|
-
|
|
1002
|
-
/**
|
|
1003
|
-
* set letter spacing property. Default value is 0.
|
|
1004
|
-
* @name Konva.Text#letterSpacing
|
|
1005
|
-
* @method
|
|
1006
|
-
* @param {Number} letterSpacing
|
|
1007
|
-
*/
|
|
1008
|
-
|
|
1009
|
-
Factory.addGetterSetter(Text, 'letterSpacing', 0, getNumberValidator());
|
|
1010
|
-
|
|
1011
|
-
/**
|
|
1012
|
-
* get/set text
|
|
1013
|
-
* @name Konva.Text#text
|
|
1014
|
-
* @method
|
|
1015
|
-
* @param {String} text
|
|
1016
|
-
* @returns {String}
|
|
1017
|
-
* @example
|
|
1018
|
-
* // get text
|
|
1019
|
-
* var text = text.text();
|
|
1020
|
-
*
|
|
1021
|
-
* // set text
|
|
1022
|
-
* text.text('Hello world!');
|
|
1023
|
-
*/
|
|
1024
|
-
|
|
1025
|
-
Factory.addGetterSetter(Text, 'text', '', getStringValidator());
|
|
1026
|
-
|
|
1027
|
-
/**
|
|
1028
|
-
* get/set text decoration of a text. Possible values are 'underline', 'line-through' or combination of these values separated by space
|
|
1029
|
-
* @name Konva.Text#textDecoration
|
|
1030
|
-
* @method
|
|
1031
|
-
* @param {String} textDecoration
|
|
1032
|
-
* @returns {String}
|
|
1033
|
-
* @example
|
|
1034
|
-
* // get text decoration
|
|
1035
|
-
* var textDecoration = text.textDecoration();
|
|
1036
|
-
*
|
|
1037
|
-
* // underline text
|
|
1038
|
-
* text.textDecoration('underline');
|
|
1039
|
-
*
|
|
1040
|
-
* // strike text
|
|
1041
|
-
* text.textDecoration('line-through');
|
|
1042
|
-
*
|
|
1043
|
-
* // underline and strike text
|
|
1044
|
-
* text.textDecoration('underline line-through');
|
|
1045
|
-
*/
|
|
1046
|
-
|
|
1047
|
-
Factory.addGetterSetter(Text, 'textDecoration', '');
|
|
1048
|
-
|
|
1049
|
-
/**
|
|
1050
|
-
* get/set per-character render hook. The callback is invoked for each grapheme before drawing.
|
|
1051
|
-
* It can mutate the provided context (e.g. translate, rotate, change styles) and should return void.
|
|
1052
|
-
* Note: per-character rendering may disable native kerning/ligatures.
|
|
1053
|
-
* @name Konva.Text#charRenderFunc
|
|
1054
|
-
* @method
|
|
1055
|
-
* @param {(props: {char: string, index: number, x: number, y: number, lineIndex: number, column: number, isLastInLine: boolean, width: number, context: Konva.Context}) => void} charRenderFunc
|
|
1056
|
-
* @returns {(props: CharRenderProps) => void}
|
|
1057
|
-
* @example
|
|
1058
|
-
* // apply small x-translation to every second character
|
|
1059
|
-
* text.charRenderFunc(function(props) {
|
|
1060
|
-
* if (props.index % 2 === 1) {
|
|
1061
|
-
* props.context.translate(2, 0);
|
|
1062
|
-
* }
|
|
1063
|
-
* });
|
|
1064
|
-
*/
|
|
1065
|
-
Factory.addGetterSetter(Text, 'charRenderFunc', undefined);
|