mirror of
https://github.com/Hopiu/fabric.js.git
synced 2026-04-30 01:54:44 +00:00
parent
cf5f327f55
commit
46624d3f50
5 changed files with 145 additions and 109 deletions
|
|
@ -398,7 +398,9 @@
|
|||
return;
|
||||
}
|
||||
|
||||
var newSelectionStart = this.getSelectionStartFromPointer(options.e);
|
||||
var newSelectionStart = this.getSelectionStartFromPointer(options.e),
|
||||
currentStart = this.selectionStart,
|
||||
currentEnd = this.selectionEnd;
|
||||
if (newSelectionStart === this.__selectionStartOnMouseDown) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -410,9 +412,11 @@
|
|||
this.selectionStart = newSelectionStart;
|
||||
this.selectionEnd = this.__selectionStartOnMouseDown;
|
||||
}
|
||||
this._fireSelectionChanged();
|
||||
this._updateTextarea();
|
||||
this.renderCursorOrSelection();
|
||||
if (this.selectionStart !== currentStart || this.selectionEnd !== currentEnd) {
|
||||
this._fireSelectionChanged();
|
||||
this._updateTextarea();
|
||||
this.renderCursorOrSelection();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -438,6 +442,7 @@
|
|||
if (!this.hiddenTextarea || this.inCompositionMode) {
|
||||
return;
|
||||
}
|
||||
this.cursorOffsetCache = { };
|
||||
this.hiddenTextarea.value = this.text;
|
||||
this.hiddenTextarea.selectionStart = this.selectionStart;
|
||||
this.hiddenTextarea.selectionEnd = this.selectionEnd;
|
||||
|
|
|
|||
|
|
@ -315,7 +315,10 @@
|
|||
this.oldHeight = this.height;
|
||||
this.callSuper('_render', ctx);
|
||||
this.ctx = ctx;
|
||||
this.isEditing && this.renderCursorOrSelection();
|
||||
// clear the cursorOffsetCache, so we ensure to calculate once per renderCursor
|
||||
// the correct position but not at every cursor animation.
|
||||
this.cursorOffsetCache = { };
|
||||
this.renderCursorOrSelection();
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -327,7 +330,6 @@
|
|||
}
|
||||
var chars = this.text.split(''),
|
||||
boundaries, ctx;
|
||||
|
||||
if (this.canvas.contextTop) {
|
||||
ctx = this.canvas.contextTop;
|
||||
ctx.save();
|
||||
|
|
@ -454,13 +456,15 @@
|
|||
* @private
|
||||
*/
|
||||
_getCursorBoundariesOffsets: function(chars, typeOfBoundaries) {
|
||||
|
||||
if (this.cursorOffsetCache && 'top' in this.cursorOffsetCache) {
|
||||
return this.cursorOffsetCache;
|
||||
}
|
||||
var lineLeftOffset = 0,
|
||||
|
||||
lineIndex = 0,
|
||||
charIndex = 0,
|
||||
topOffset = 0,
|
||||
leftOffset = 0;
|
||||
leftOffset = 0,
|
||||
boundaries;
|
||||
|
||||
for (var i = 0; i < this.selectionStart; i++) {
|
||||
if (chars[i] === '\n') {
|
||||
|
|
@ -481,12 +485,16 @@
|
|||
topOffset += (1 - this._fontSizeFraction) * this._getHeightOfLine(this.ctx, lineIndex) / this.lineHeight
|
||||
- this.getCurrentCharFontSize(lineIndex, charIndex) * (1 - this._fontSizeFraction);
|
||||
}
|
||||
|
||||
return {
|
||||
if (this.charSpacing !== 0 && charIndex === this._textLines[lineIndex].length) {
|
||||
leftOffset -= this._getWidthOfCharSpacing();
|
||||
}
|
||||
boundaries = {
|
||||
top: topOffset,
|
||||
left: leftOffset,
|
||||
lineLeft: lineLeftOffset
|
||||
};
|
||||
this.cursorOffsetCache = boundaries;
|
||||
return this.cursorOffsetCache;
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -544,6 +552,9 @@
|
|||
lineOffset += this._getWidthOfChar(ctx, line[j], i, j);
|
||||
}
|
||||
}
|
||||
if (j === line.length) {
|
||||
boxWidth -= this._getWidthOfCharSpacing();
|
||||
}
|
||||
}
|
||||
else if (i > startLine && i < endLine) {
|
||||
boxWidth += this._getLineWidth(ctx, i) || 5;
|
||||
|
|
@ -552,6 +563,9 @@
|
|||
for (var j2 = 0, j2len = end.charIndex; j2 < j2len; j2++) {
|
||||
boxWidth += this._getWidthOfChar(ctx, line[j2], i, j2);
|
||||
}
|
||||
if (end.charIndex === line.length) {
|
||||
boxWidth -= this._getWidthOfCharSpacing();
|
||||
}
|
||||
}
|
||||
realLineHeight = lineHeight;
|
||||
if (this.lineHeight < 1 || (i === endLine && this.lineHeight > 1)) {
|
||||
|
|
@ -579,24 +593,13 @@
|
|||
}
|
||||
|
||||
charOffset = charOffset || 0;
|
||||
this.skipTextAlign = true;
|
||||
|
||||
// set proper box offset
|
||||
left -= this.textAlign === 'center'
|
||||
? (this.width / 2)
|
||||
: (this.textAlign === 'right')
|
||||
? this.width
|
||||
: 0;
|
||||
|
||||
// set proper line offset
|
||||
var lineHeight = this._getHeightOfLine(ctx, lineIndex),
|
||||
lineLeftOffset = this._getLineLeftOffset(this._getLineWidth(ctx, lineIndex)),
|
||||
prevStyle,
|
||||
thisStyle,
|
||||
charsToRender = '';
|
||||
|
||||
left += lineLeftOffset || 0;
|
||||
|
||||
ctx.save();
|
||||
top -= lineHeight / this.lineHeight * this._fontSizeFraction;
|
||||
for (var i = charOffset, len = line.length + charOffset; i <= len; i++) {
|
||||
|
|
@ -622,7 +625,6 @@
|
|||
* @param {Number} top Top coordinate
|
||||
*/
|
||||
_renderCharsFast: function(method, ctx, line, left, top) {
|
||||
this.skipTextAlign = false;
|
||||
|
||||
if (method === 'fillText' && this.fill) {
|
||||
this.callSuper('_renderChars', method, ctx, line, left, top);
|
||||
|
|
@ -646,7 +648,7 @@
|
|||
_renderChar: function(method, ctx, lineIndex, i, _char, left, top, lineHeight) {
|
||||
var charWidth, charHeight, shouldFill, shouldStroke,
|
||||
decl = this._getStyleDeclaration(lineIndex, i),
|
||||
offset, textDecoration;
|
||||
offset, textDecoration, chars;
|
||||
|
||||
if (decl) {
|
||||
charHeight = this._getHeightOfChar(ctx, _char, lineIndex, i);
|
||||
|
|
@ -663,14 +665,26 @@
|
|||
|
||||
decl && ctx.save();
|
||||
|
||||
charWidth = this._applyCharStylesGetWidth(ctx, _char, lineIndex, i, decl || {});
|
||||
charWidth = this._applyCharStylesGetWidth(ctx, _char, lineIndex, i, decl || null);
|
||||
textDecoration = textDecoration || this.textDecoration;
|
||||
|
||||
if (decl && decl.textBackgroundColor) {
|
||||
this._removeShadow(ctx);
|
||||
}
|
||||
shouldFill && ctx.fillText(_char, left, top);
|
||||
shouldStroke && ctx.strokeText(_char, left, top);
|
||||
if (this.charSpacing !== 0) {
|
||||
chars = _char.split('');
|
||||
charWidth = 0;
|
||||
for (var j = 0, len = chars.length, char; j < len; j++) {
|
||||
char = chars[j];
|
||||
shouldFill && ctx.fillText(char, left + charWidth, top);
|
||||
shouldStroke && ctx.strokeText(char, left + charWidth, top);
|
||||
charWidth += ctx.measureText(char).width + this._getWidthOfCharSpacing();
|
||||
}
|
||||
}
|
||||
else {
|
||||
shouldFill && ctx.fillText(_char, left, top);
|
||||
shouldStroke && ctx.strokeText(_char, left, top);
|
||||
}
|
||||
|
||||
if (textDecoration || textDecoration !== '') {
|
||||
offset = this._fontSizeFraction * lineHeight / this.lineHeight;
|
||||
|
|
@ -826,8 +840,8 @@
|
|||
* @param {Object} [decl]
|
||||
*/
|
||||
_applyCharStylesGetWidth: function(ctx, _char, lineIndex, charIndex, decl) {
|
||||
var charDecl = this._getStyleDeclaration(lineIndex, charIndex),
|
||||
styleDeclaration = (decl && clone(decl)) || clone(charDecl),
|
||||
var charDecl = decl || this._getStyleDeclaration(lineIndex, charIndex),
|
||||
styleDeclaration = clone(charDecl),
|
||||
width, cacheProp, charWidthsCache;
|
||||
|
||||
this._applyFontStyles(styleDeclaration);
|
||||
|
|
@ -964,21 +978,13 @@
|
|||
if (!this._isMeasuring && this.textAlign === 'justify' && this._reSpacesAndTabs.test(_char)) {
|
||||
return this._getWidthOfSpace(ctx, lineIndex);
|
||||
}
|
||||
var charWidthsCache, cacheProp,
|
||||
styleDeclaration = this._getStyleDeclaration(lineIndex, charIndex, true);
|
||||
this._applyFontStyles(styleDeclaration);
|
||||
charWidthsCache = this._getFontCache(styleDeclaration.fontFamily);
|
||||
cacheProp = this._getCacheProp(_char, styleDeclaration);
|
||||
|
||||
if (charWidthsCache[cacheProp] && this.caching) {
|
||||
return charWidthsCache[cacheProp];
|
||||
}
|
||||
else if (ctx) {
|
||||
ctx.save();
|
||||
var width = this._applyCharStylesGetWidth(ctx, _char, lineIndex, charIndex);
|
||||
ctx.restore();
|
||||
return width;
|
||||
ctx.save();
|
||||
var width = this._applyCharStylesGetWidth(ctx, _char, lineIndex, charIndex);
|
||||
if (this.charSpacing !== 0) {
|
||||
width += this._getWidthOfCharSpacing();
|
||||
}
|
||||
ctx.restore();
|
||||
return width;
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -1014,6 +1020,9 @@
|
|||
_measureLine: function(ctx, lineIndex) {
|
||||
this._isMeasuring = true;
|
||||
var width = this._getWidthOfCharsAt(ctx, lineIndex, this._textLines[lineIndex].length);
|
||||
if (this.charSpacing !== 0) {
|
||||
width -= this._getWidthOfCharSpacing();
|
||||
}
|
||||
this._isMeasuring = false;
|
||||
return width;
|
||||
},
|
||||
|
|
@ -1039,8 +1048,9 @@
|
|||
/**
|
||||
* @private
|
||||
* @param {CanvasRenderingContext2D} ctx Context to render on
|
||||
* @param {Number} line
|
||||
* @param {String} line
|
||||
* @param {Number} lineIndex
|
||||
* @param {Number} charOffset
|
||||
*/
|
||||
_getWidthOfWords: function (ctx, line, lineIndex, charOffset) {
|
||||
var width = 0;
|
||||
|
|
|
|||
|
|
@ -48,10 +48,11 @@
|
|||
fontFamily: true,
|
||||
fontStyle: true,
|
||||
lineHeight: true,
|
||||
stroke: true,
|
||||
strokeWidth: true,
|
||||
text: true,
|
||||
textAlign: true
|
||||
charSpacing: true,
|
||||
textAlign: true,
|
||||
stroke: false,
|
||||
strokeWidth: false,
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -319,6 +320,14 @@
|
|||
*/
|
||||
_fontSizeMult: 1.13,
|
||||
|
||||
/**
|
||||
* additional space between characters
|
||||
* expressed in thousands of em unit
|
||||
* @type Number
|
||||
* @default
|
||||
*/
|
||||
charSpacing: 0,
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param {String} text Text string
|
||||
|
|
@ -387,23 +396,8 @@
|
|||
* @param {CanvasRenderingContext2D} ctx Context to render on
|
||||
*/
|
||||
_renderText: function(ctx) {
|
||||
|
||||
this._translateForTextAlign(ctx);
|
||||
this._renderTextFill(ctx);
|
||||
this._renderTextStroke(ctx);
|
||||
this._translateForTextAlign(ctx, true);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {CanvasRenderingContext2D} ctx Context to render on
|
||||
* @param {Boolean} back Indicates if translate back or forward
|
||||
*/
|
||||
_translateForTextAlign: function(ctx, back) {
|
||||
if (this.textAlign !== 'left' && this.textAlign !== 'justify') {
|
||||
var sign = back ? -1 : 1;
|
||||
ctx.translate(this.textAlign === 'center' ? (sign * this.width / 2) : sign * this.width, 0);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -412,9 +406,6 @@
|
|||
*/
|
||||
_setTextStyles: function(ctx) {
|
||||
ctx.textBaseline = 'alphabetic';
|
||||
if (!this.skipTextAlign) {
|
||||
ctx.textAlign = this.textAlign;
|
||||
}
|
||||
ctx.font = this._getFontDeclaration();
|
||||
},
|
||||
|
||||
|
|
@ -463,7 +454,7 @@
|
|||
*/
|
||||
_renderChars: function(method, ctx, chars, left, top) {
|
||||
// remove Text word from method var
|
||||
var shortM = method.slice(0, -4);
|
||||
var shortM = method.slice(0, -4), char, width;
|
||||
if (this[shortM].toLive) {
|
||||
var offsetX = -this.width / 2 + this[shortM].offsetX || 0,
|
||||
offsetY = -this.height / 2 + this[shortM].offsetY || 0;
|
||||
|
|
@ -472,7 +463,19 @@
|
|||
left -= offsetX;
|
||||
top -= offsetY;
|
||||
}
|
||||
ctx[method](chars, left, top);
|
||||
if (this.charSpacing !== 0) {
|
||||
var additionalSpace = this._getWidthOfCharSpacing();
|
||||
chars = chars.split('');
|
||||
for (var i = 0, len = chars.length; i < len; i++) {
|
||||
char = chars[i];
|
||||
width = ctx.measureText(char).width + additionalSpace;
|
||||
ctx[method](char, left, top);
|
||||
left += width;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ctx[method](chars, left, top);
|
||||
}
|
||||
this[shortM].toLive && ctx.restore();
|
||||
},
|
||||
|
||||
|
|
@ -499,7 +502,7 @@
|
|||
// stretch the line
|
||||
var words = line.split(/\s+/),
|
||||
charOffset = 0,
|
||||
wordsWidth = this._getWidthOfWords(ctx, line, lineIndex, 0),
|
||||
wordsWidth = this._getWidthOfWords(ctx, words.join(''), lineIndex, 0),
|
||||
widthDiff = this.width - wordsWidth,
|
||||
numSpaces = words.length - 1,
|
||||
spaceWidth = numSpaces > 0 ? widthDiff / numSpaces : 0,
|
||||
|
|
@ -519,10 +522,16 @@
|
|||
/**
|
||||
* @private
|
||||
* @param {CanvasRenderingContext2D} ctx Context to render on
|
||||
* @param {Number} line
|
||||
* @param {String} word
|
||||
*/
|
||||
_getWidthOfWords: function (ctx, line) {
|
||||
return ctx.measureText(line.replace(/\s+/g, '')).width;
|
||||
_getWidthOfWords: function (ctx, word) {
|
||||
var width = ctx.measureText(word).width, charCount, additionalSpace;
|
||||
if (this.charSpacing !== 0) {
|
||||
charCount = word.split('').length;
|
||||
additionalSpace = charCount * this._getWidthOfCharSpacing();
|
||||
width += additionalSpace;
|
||||
}
|
||||
return width;
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -552,29 +561,39 @@
|
|||
* @private
|
||||
* @param {CanvasRenderingContext2D} ctx Context to render on
|
||||
*/
|
||||
_renderTextFill: function(ctx) {
|
||||
if (!this.fill && this.isEmptyStyles()) {
|
||||
return;
|
||||
}
|
||||
_renderTextCommon: function(ctx, method) {
|
||||
|
||||
var lineHeights = 0;
|
||||
var lineHeights = 0, left = this._getLeftOffset(), top = this._getTopOffset();
|
||||
|
||||
for (var i = 0, len = this._textLines.length; i < len; i++) {
|
||||
var heightOfLine = this._getHeightOfLine(ctx, i),
|
||||
maxHeight = heightOfLine / this.lineHeight;
|
||||
|
||||
maxHeight = heightOfLine / this.lineHeight,
|
||||
lineWidth = this._getLineWidth(ctx, i),
|
||||
leftOffset = this._getLineLeftOffset(lineWidth);
|
||||
this._renderTextLine(
|
||||
'fillText',
|
||||
method,
|
||||
ctx,
|
||||
this._textLines[i],
|
||||
this._getLeftOffset(),
|
||||
this._getTopOffset() + lineHeights + maxHeight,
|
||||
left + leftOffset,
|
||||
top + lineHeights + maxHeight,
|
||||
i
|
||||
);
|
||||
lineHeights += heightOfLine;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {CanvasRenderingContext2D} ctx Context to render on
|
||||
*/
|
||||
_renderTextFill: function(ctx) {
|
||||
if (!this.fill && this.isEmptyStyles()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._renderTextCommon(ctx, 'fillText');
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {CanvasRenderingContext2D} ctx Context to render on
|
||||
|
|
@ -584,8 +603,6 @@
|
|||
return;
|
||||
}
|
||||
|
||||
var lineHeights = 0;
|
||||
|
||||
if (this.shadow && !this.shadow.affectStroke) {
|
||||
this._removeShadow(ctx);
|
||||
}
|
||||
|
|
@ -601,20 +618,7 @@
|
|||
}
|
||||
|
||||
ctx.beginPath();
|
||||
for (var i = 0, len = this._textLines.length; i < len; i++) {
|
||||
var heightOfLine = this._getHeightOfLine(ctx, i),
|
||||
maxHeight = heightOfLine / this.lineHeight;
|
||||
|
||||
this._renderTextLine(
|
||||
'strokeText',
|
||||
ctx,
|
||||
this._textLines[i],
|
||||
this._getLeftOffset(),
|
||||
this._getTopOffset() + lineHeights + maxHeight,
|
||||
i
|
||||
);
|
||||
lineHeights += heightOfLine;
|
||||
}
|
||||
this._renderTextCommon(ctx, 'strokeText');
|
||||
ctx.closePath();
|
||||
ctx.restore();
|
||||
},
|
||||
|
|
@ -769,6 +773,13 @@
|
|||
return width;
|
||||
},
|
||||
|
||||
_getWidthOfCharSpacing: function() {
|
||||
if (this.charSpacing !== 0) {
|
||||
return this.fontSize * this.charSpacing / 1000;
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {CanvasRenderingContext2D} ctx Context to render on
|
||||
|
|
@ -776,7 +787,14 @@
|
|||
* @return {Number} Line width
|
||||
*/
|
||||
_measureLine: function(ctx, lineIndex) {
|
||||
return ctx.measureText(this._textLines[lineIndex]).width;
|
||||
var line = this._textLines[lineIndex],
|
||||
width = ctx.measureText(line).width,
|
||||
additionalSpace = 0, charCount;
|
||||
if (this.charSpacing !== 0) {
|
||||
charCount = line.split('').length;
|
||||
additionalSpace = (charCount - 1) * this._getWidthOfCharSpacing();
|
||||
}
|
||||
return width + additionalSpace;
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -787,7 +805,6 @@
|
|||
if (!this.textDecoration) {
|
||||
return;
|
||||
}
|
||||
|
||||
var halfOfVerticalBox = this.height / 2,
|
||||
_this = this, offsets = [];
|
||||
|
||||
|
|
@ -1012,7 +1029,7 @@
|
|||
|
||||
var line = this._textLines[i],
|
||||
words = line.split(/\s+/),
|
||||
wordsWidth = this._getWidthOfWords(ctx, line),
|
||||
wordsWidth = this._getWidthOfWords(ctx, words.join('')),
|
||||
widthDiff = this.width - wordsWidth,
|
||||
numSpaces = words.length - 1,
|
||||
spaceWidth = numSpaces > 0 ? widthDiff / numSpaces : 0,
|
||||
|
|
|
|||
|
|
@ -94,7 +94,6 @@
|
|||
|
||||
// wrap lines
|
||||
this._textLines = this._splitTextIntoLines();
|
||||
|
||||
// if after wrapping, the width is smaller than dynamicMinWidth, change the width and re-wrap
|
||||
if (this.dynamicMinWidth > this.width) {
|
||||
this._set('width', this.dynamicMinWidth);
|
||||
|
|
@ -244,11 +243,9 @@
|
|||
_measureText: function(ctx, text, lineIndex, charOffset) {
|
||||
var width = 0;
|
||||
charOffset = charOffset || 0;
|
||||
|
||||
for (var i = 0, len = text.length; i < len; i++) {
|
||||
width += this._getWidthOfChar(ctx, text[i], lineIndex, i + charOffset);
|
||||
}
|
||||
|
||||
return width;
|
||||
},
|
||||
|
||||
|
|
@ -271,7 +268,8 @@
|
|||
wordWidth = 0,
|
||||
infixWidth = 0,
|
||||
largestWordWidth = 0,
|
||||
lineJustStarted = true;
|
||||
lineJustStarted = true,
|
||||
additionalSpace = this._getWidthOfCharSpacing();
|
||||
|
||||
for (var i = 0; i < words.length; i++) {
|
||||
word = words[i];
|
||||
|
|
@ -279,7 +277,7 @@
|
|||
|
||||
offset += word.length;
|
||||
|
||||
lineWidth += infixWidth + wordWidth;
|
||||
lineWidth += infixWidth + wordWidth - additionalSpace;
|
||||
|
||||
if (lineWidth >= this.width && !lineJustStarted) {
|
||||
lines.push(line);
|
||||
|
|
@ -287,13 +285,16 @@
|
|||
lineWidth = wordWidth;
|
||||
lineJustStarted = true;
|
||||
}
|
||||
else {
|
||||
lineWidth += additionalSpace;
|
||||
}
|
||||
|
||||
if (!lineJustStarted) {
|
||||
line += infix;
|
||||
}
|
||||
line += word;
|
||||
|
||||
infixWidth = this._measureText(ctx, infix, lineIndex, offset);
|
||||
infixWidth = this._measureText(ctx, infix, lineIndex, offset) + additionalSpace;
|
||||
offset++;
|
||||
lineJustStarted = false;
|
||||
// keep track of largest word
|
||||
|
|
@ -305,7 +306,7 @@
|
|||
i && lines.push(line);
|
||||
|
||||
if (largestWordWidth > this.dynamicMinWidth) {
|
||||
this.dynamicMinWidth = largestWordWidth;
|
||||
this.dynamicMinWidth = largestWordWidth - additionalSpace;
|
||||
}
|
||||
|
||||
return lines;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
(function(){
|
||||
var canvas = fabric.document.createElement('canvas'),
|
||||
ctx = canvas.getContext('2d');
|
||||
|
||||
test('event selection:changed firing', function() {
|
||||
var iText = new fabric.IText('test need some word\nsecond line'),
|
||||
selection = 0;
|
||||
|
||||
iText.ctx = ctx;
|
||||
function countSelectionChange() {
|
||||
selection++;
|
||||
}
|
||||
|
|
@ -133,7 +136,7 @@
|
|||
test('moving cursor with shift', function() {
|
||||
var iText = new fabric.IText('test need some word\nsecond line'),
|
||||
selection = 0;
|
||||
|
||||
iText.ctx = ctx;
|
||||
function countSelectionChange() {
|
||||
selection++;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue