123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- import { MarkerType } from '../types';
- import { RectangularMarker } from '../RectangularMarker';
- import { SvgHelper } from '../../renderer/SvgHelper';
- import { PositionType } from 'fc-whiteboard/src/event/Event';
- import { WhitePage } from 'fc-whiteboard/src/board/WhitePage';
-
- const OkIcon = require('../../assets/check.svg');
- const CancelIcon = require('../../assets/times.svg');
-
- export class TextMarker extends RectangularMarker {
- type: MarkerType = 'text';
-
- public static createMarker = (page?: WhitePage): TextMarker => {
- const marker = new TextMarker();
- marker.page = page;
- marker.setup();
- return marker;
- };
-
- /** 设置文本 */
- public setText(text: string) {
- this.text = text;
- this.renderText();
- }
-
- protected readonly MIN_SIZE = 50;
-
- private readonly DEFAULT_TEXT = 'Double-click to edit text';
- private text: string = this.DEFAULT_TEXT;
- private textElement: SVGTextElement;
-
- private inDoubleTap = false;
-
- private editor: HTMLDivElement;
-
- private editorTextArea: HTMLTextAreaElement;
-
- protected setup() {
- super.setup();
- this.textElement = SvgHelper.createText();
- this.addToRenderVisual(this.textElement);
- SvgHelper.setAttributes(this.visual, [['class', 'text-marker']]);
-
- this.textElement.transform.baseVal.appendItem(SvgHelper.createTransform()); // translate transorm
- this.textElement.transform.baseVal.appendItem(SvgHelper.createTransform()); // scale transorm
-
- this.renderText();
-
- this.visual.addEventListener('dblclick', this.onDblClick);
- this.visual.addEventListener('touchstart', this.onTap);
- }
-
- protected resize(x: number, y: number, onPosition?: (pos: PositionType) => void) {
- super.resize(x, y, onPosition);
-
- this.sizeText();
- }
-
- private renderText = () => {
- const LINE_SIZE = '1.2em';
-
- while (this.textElement.lastChild) {
- this.textElement.removeChild(this.textElement.lastChild);
- }
-
- const lines = this.text.split(/\r\n|[\n\v\f\r\x85\u2028\u2029]/);
- for (let line of lines) {
- if (line.trim() === '') {
- line = ' '; // workaround for swallowed empty lines
- }
- this.textElement.appendChild(SvgHelper.createTSpan(line, [['x', '0'], ['dy', LINE_SIZE]]));
- }
-
- setTimeout(this.sizeText, 10);
- };
-
- private sizeText = () => {
- const textSize = this.textElement.getBBox();
- let x = 0;
- let y = 0;
- let scale = 1.0;
- if (textSize.width > 0 && textSize.height > 0) {
- const xScale = (this.width * 1.0) / textSize.width;
- const yScale = (this.height * 1.0) / textSize.height;
- scale = Math.min(xScale, yScale);
-
- x = (this.width - textSize.width * scale) / 2;
- y = (this.height - textSize.height * scale) / 2;
- }
-
- this.textElement.transform.baseVal.getItem(0).setTranslate(x, y);
- this.textElement.transform.baseVal.getItem(1).setScale(scale, scale);
- };
-
- private onDblClick = (ev: MouseEvent) => {
- this.showEditor();
- };
-
- private onTap = (ev: TouchEvent) => {
- if (this.inDoubleTap) {
- this.inDoubleTap = false;
- this.showEditor();
- } else {
- this.inDoubleTap = true;
- setTimeout(() => {
- this.inDoubleTap = false;
- }, 300);
- }
- };
-
- private showEditor = () => {
- this.editor = document.createElement('div');
- this.editor.className = 'fc-whiteboard-text-editor';
-
- this.editorTextArea = document.createElement('textarea');
- if (this.text !== this.DEFAULT_TEXT) {
- this.editorTextArea.value = this.text;
- }
- this.editorTextArea.addEventListener('keydown', this.onEditorKeyDown);
- this.editor.appendChild(this.editorTextArea);
-
- document.body.appendChild(this.editor);
-
- const buttons = document.createElement('div');
- buttons.className = 'fc-whiteboard-text-editor-button-bar';
- this.editor.appendChild(buttons);
-
- const okButton = document.createElement('div');
- okButton.className = 'fc-whiteboard-text-editor-button';
- okButton.innerHTML = OkIcon;
- okButton.addEventListener('click', this.onEditorOkClick);
- buttons.appendChild(okButton);
-
- const cancelButton = document.createElement('div');
- cancelButton.className = 'fc-whiteboard-text-editor-button';
- cancelButton.innerHTML = CancelIcon;
- cancelButton.addEventListener('click', this.closeEditor);
- buttons.appendChild(cancelButton);
- };
-
- /** 响应文本输入的事件 */
- private onEditorOkClick = (ev: MouseEvent | null) => {
- if (this.editorTextArea.value.trim()) {
- this.text = this.editorTextArea.value;
- } else {
- this.text = this.DEFAULT_TEXT;
- }
-
- // 触发文本修改时间
- this.onChange({ target: 'marker', id: this.id, event: 'changeText', data: this.text });
-
- this.renderText();
- this.closeEditor();
- };
-
- private closeEditor = () => {
- document.body.removeChild(this.editor);
- };
-
- private onEditorKeyDown = (ev: KeyboardEvent) => {
- if (ev.key === 'Enter' && ev.ctrlKey) {
- ev.preventDefault();
- this.onEditorOkClick(null);
- }
- };
- }
|