Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: fixed Text object -> ITextObject (fix #262 #109) #352

Merged
merged 4 commits into from
Jun 16, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
195 changes: 31 additions & 164 deletions src/js/component/text.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,7 @@ const resetStyles = {
textAlign: 'left',
underline: false
};
const {browser} = snippet;

const TEXTAREA_CLASSNAME = 'tui-image-eidtor-textarea';
const TEXTAREA_STYLES = makeStyleText({
position: 'absolute',
padding: 0,
display: 'none',
border: '1px dotted red',
overflow: 'hidden',
resize: 'none',
outline: 'none',
'border-radius': 0,
'background-color': 'transparent',
'-webkit-appearance': 'none',
'z-index': 9999,
'white-space': 'pre'
});
const EXTRA_PIXEL_LINEHEIGHT = 0.1;

const DBCLICK_TIME = 500;

/**
Expand Down Expand Up @@ -115,12 +98,6 @@ class Text extends Component {
* @type {boolean}
*/
this.isPrevEditing = false;

/**
* use itext
* @type {boolean}
*/
this.useItext = graphics.useItext;
}

/**
Expand All @@ -139,20 +116,16 @@ class Text extends Component {
'text:editing': this._listeners.modify
});

if (this.useItext) {
canvas.forEachObject(obj => {
if (obj.type === 'i-text') {
obj.set({
left: obj.left - (obj.width / 2),
top: obj.top - (obj.height / 2),
originX: 'left',
originY: 'top'
});
}
});
} else {
this._createTextarea();
}
canvas.forEachObject(obj => {
if (obj.type === 'i-text') {
obj.set({
left: obj.left - (obj.width / 2),
top: obj.top - (obj.height / 2),
originX: 'left',
originY: 'top'
});
}
});

this.setCanvasRatio();
}
Expand All @@ -166,25 +139,20 @@ class Text extends Component {
canvas.selection = true;
canvas.defaultCursor = 'default';

if (this.useItext) {
canvas.forEachObject(obj => {
if (obj.type === 'i-text') {
if (obj.text === '') {
canvas.remove(obj);
} else {
obj.set({
left: obj.left + (obj.width / 2),
top: obj.top + (obj.height / 2),
originX: 'center',
originY: 'center'
});
}
canvas.forEachObject(obj => {
if (obj.type === 'i-text') {
if (obj.text === '') {
canvas.remove(obj);
} else {
obj.set({
left: obj.left + (obj.width / 2),
top: obj.top + (obj.height / 2),
originX: 'center',
originY: 'center'
});
}
});
} else {
canvas.discardActiveObject();
this._removeTextarea();
}
}
});

canvas.off({
'mouse:down': this._listeners.mousedown,
Expand Down Expand Up @@ -223,15 +191,11 @@ class Text extends Component {
styles = snippet.extend(styles, options.styles);
}

if (this.useItext) {
newText = new fabric.IText(text, styles);
selectionStyle = snippet.extend({}, selectionStyle, {
originX: 'left',
originY: 'top'
});
} else {
newText = new fabric.Text(text, styles);
}
newText = new fabric.IText(text, styles);
selectionStyle = snippet.extend({}, selectionStyle, {
originX: 'left',
originY: 'top'
});

newText.set(selectionStyle);
newText.on({
Expand Down Expand Up @@ -376,59 +340,6 @@ class Text extends Component {
this._defaultStyles.top = position.y;
}

/**
* Create textarea element on canvas container
* @private
*/
_createTextarea() {
const container = this.getCanvasElement().parentNode;
const textarea = document.createElement('textarea');

textarea.className = TEXTAREA_CLASSNAME;
textarea.setAttribute('style', TEXTAREA_STYLES);
textarea.setAttribute('wrap', 'off');

container.appendChild(textarea);

this._textarea = textarea;

this._listeners = snippet.extend(this._listeners, {
input: this._onInput.bind(this),
keydown: this._onKeyDown.bind(this),
blur: this._onBlur.bind(this),
scroll: this._onScroll.bind(this)
});

if (browser.msie && browser.version === 9) {
fabric.util.addListener(textarea, 'keydown', this._listeners.keydown);
} else {
fabric.util.addListener(textarea, 'input', this._listeners.input);
}
fabric.util.addListener(textarea, 'blur', this._listeners.blur);
fabric.util.addListener(textarea, 'scroll', this._listeners.scroll);
}

/**
* Remove textarea element on canvas container
* @private
*/
_removeTextarea() {
const container = this.getCanvasElement().parentNode;
const textarea = container.querySelector('textarea');

container.removeChild(textarea);

this._textarea = null;

if (browser.msie && browser.version < 10) {
fabric.util.removeListener(textarea, 'keydown', this._listeners.keydown);
} else {
fabric.util.removeListener(textarea, 'input', this._listeners.input);
}
fabric.util.removeListener(textarea, 'blur', this._listeners.blur);
fabric.util.removeListener(textarea, 'scroll', this._listeners.scroll);
}

/**
* Input event handler
* @private
Expand Down Expand Up @@ -605,8 +516,8 @@ class Text extends Component {
const newClickTime = (new Date()).getTime();

if (target.isEditing || this._isDoubleClick(newClickTime)) {
if (!this.useItext) {
this._changeToEditingMode(target);
if (!target.isEditing) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

target.isEditing 조건문이 true인 경우에도 이 라인까지 들어왔다가 이벤트를 날리네요. 에디팅 중에 마우스업이나 더블 클릭인 경우 이벤트가 다시 한 번 더 날아갈 것 같은데 문제 없는지 확인 필요해 보여요.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵 이부분 확인해보고 수정하겠습니다. 리뷰 감사합니다

target.enterEditing();
}
this.fire(events.TEXT_EDITING); // fire editing text event
}
Expand All @@ -623,50 +534,6 @@ class Text extends Component {
_isDoubleClick(newClickTime) {
return (newClickTime - this._lastClickTime < DBCLICK_TIME);
}

/**
* Change state of text object for editing
* @param {fabric.Text} obj - Text object fired event
* @private
*/
_changeToEditingMode(obj) {
const ratio = this.getCanvasRatio();
const textareaStyle = this._textarea.style;
const canvas = this.getCanvas();

this.isPrevEditing = true;

canvas.remove(obj);
canvas.discardActiveObject();

this._editingObj = obj;
this._textarea.value = obj.text;

this._editingObjInfos = {
left: obj.left,
top: obj.top,
width: obj.width,
height: obj.height
};

textareaStyle.display = 'block';
textareaStyle.left = `${obj.oCoords.tl.x / ratio}px`;
textareaStyle.top = `${obj.oCoords.tl.y / ratio}px`;
textareaStyle.width = `${Math.ceil(obj.width / ratio)}px`;
textareaStyle.height = `${Math.ceil(obj.height / ratio)}px`;
textareaStyle.transform = `rotate(${obj.angle}deg)`;
textareaStyle.color = obj.fill;

textareaStyle['font-size'] = `${obj.fontSize / ratio}px`;
textareaStyle['font-family'] = obj.fontFamily;
textareaStyle['font-style'] = obj.fontStyle;
textareaStyle['font-weight'] = obj.fontWeight;
textareaStyle['text-align'] = obj.textAlign;
textareaStyle['line-height'] = obj.lineHeight + EXTRA_PIXEL_LINEHEIGHT;
textareaStyle['transform-origin'] = 'left top';

this._textarea.focus();
}
}

export default Text;
8 changes: 0 additions & 8 deletions src/js/graphics.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,13 @@ const backstoreOnly = {
* @param {Object} [option] - Canvas max width & height of css
* @param {number} option.cssMaxWidth - Canvas css-max-width
* @param {number} option.cssMaxHeight - Canvas css-max-height
* @param {boolean} option.useItext - Use IText in text mode
* @param {boolean} option.useDragAddIcon - Use dragable add in icon mode
* @ignore
*/
class Graphics {
constructor(element, {
cssMaxWidth,
cssMaxHeight,
useItext = false,
useDragAddIcon = false
} = {}) {
/**
Expand All @@ -70,12 +68,6 @@ class Graphics {
*/
this.cssMaxHeight = cssMaxHeight || DEFAULT_CSS_MAX_HEIGHT;

/**
* Use Itext mode for text component
* @type {boolean}
*/
this.useItext = useItext;

/**
* Use add drag icon mode for icon component
* @type {boolean}
Expand Down
1 change: 0 additions & 1 deletion src/js/imageEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,6 @@ class ImageEditor {
this.ui ? this.ui.getEditorArea() : wrapper, {
cssMaxWidth: options.cssMaxWidth,
cssMaxHeight: options.cssMaxHeight,
useItext: !!this.ui,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

기본 ui 일때만 itext 를 쓰도록 되어있었네요, 기본 ui를 사용 하지 않는 경우에도 문제가 없나요?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵 확인 해봤었는데 문제 없었고, 휴직 전에 작업해던거라서.. 한번 더 확인해보겠습니다.

useDragAddIcon: !!this.ui
}
);
Expand Down
97 changes: 0 additions & 97 deletions test/text.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,59 +100,6 @@ describe('Text', () => {
});
});

describe('_createTextarea()', () => {
let $textarea;

beforeEach(() => {
text._createTextarea();

$textarea = $(text.getCanvasElement().parentNode).find('textarea');
});

afterEach(() => {
text._removeTextarea();
});

it('should attach the created "textarea" element on canvas container.', () => {
expect($textarea.length).toEqual(1);
});

it('should have class name.', () => {
const expected = 'tui-image-eidtor-textarea';

expect($textarea.attr('class')).toEqual(expected);
});

it('should add inline style on "textarea" element.', () => {
expect($textarea.attr('style')).not.toEqual(null);
});
});

it('_removeTextarea() should remove "textarea" element on canvas container.', () => {
text._createTextarea();
text._removeTextarea();

const $textarea = $(text.getCanvasElement().parentNode).find('textarea');

expect($textarea.length).toEqual(0);
});

it('_onBlur() should hide the "textarea" element.', () => {
const obj = new fabric.Text('test');

text._createTextarea();

const $textarea = $(text.getCanvasElement().parentNode).find('textarea');

text._editingObj = obj;

canvas.add(obj);

text._onBlur();

expect($textarea.css('display')).toEqual('none');
});

it('_onFabricScaling() should change size of selected text object.', () => {
const obj = new fabric.Text('test');
const mock = {
Expand All @@ -170,48 +117,4 @@ describe('Text', () => {

expect(obj.fontSize).toEqual(originSize * scale);
});

describe('_changeToEditingMode()', () => {
let textarea;
const ratio = 10;
const expected = {
fontSize: 12,
fontFamily: 'Comic Sans',
fontStyle: 'italic',
fontWeight: '700',
textAlign: 'right',
lineHeight: '3'
};
const obj = new fabric.Text('test', expected);

beforeEach(() => {
text._createTextarea();

textarea = text._textarea;

canvas.add(obj);

spyOn(text, 'getCanvasRatio').and.returnValue(ratio);

text._changeToEditingMode(obj);
});

afterEach(() => {
text._removeTextarea();
});

it('should change selected text object into textarea.', () => {
expect(textarea.style.display).not.toEqual('none');
});

it('should set style of textarea by selected text object.', () => {
const textareaStyles = textarea.style;

expect(textareaStyles['font-size']).toEqual(`${expected.fontSize / ratio}px`);
expect(textareaStyles['font-family'].replace(/'|"|\\/g, '')).toEqual(expected.fontFamily);
expect(textareaStyles['font-weight']).toEqual(expected.fontWeight);
expect(textareaStyles['font-align']).toEqual(expected.fontAlign);
expect(textareaStyles['line-height']).toEqual(obj.lineHeight + 0.1);
});
});
});